[] HNOI2012 build mines

Face questions

https://www.luogu.org/problem/P3225

answer

First image of a prior understanding of the cut point this thing.

A cut point is two or more pairs of cross points, so it can not be understood as an edge on the "tree formed after condensing point."

Can also be understood as a two-point boundary is a boundary map and can not, so I think the cut point is not very beautiful.

Dual between two points, at most one cut point (or else would not be called a cut point)

Cut point of comparison and bridges:

Point demanding double, double points are so small, so easy to find cut points. ($ Low [y]> = dfn [x] $) (say, in this process, the parent can not be updated edge $ low [x] $ not affect the results)

Double edge is not critical, so double edge is relatively large, it is difficult to find a cutting edge. ($ Low [y]> dfn [x] $) (in this process, obviously can not be updated)

Besides cutting method for finding the point (I do not write many years I had forgotten)

When $ low [y]> = dfn [x] $, should be popped, until the shells $ Y $, then $ X $ "to count" bis inside this point (if popped to $ X $, the first search the following has been determined and $ x $ form part of a two-point, it was classified as the point where a double, but in fact, these parts should be $ x $ and $ x $ is a point above the point where the double )

Such two-point demand is not part of the sentence to be special.

But seeking a cut point of time, because it is not a point on the border, so when $ x $ is the root, to be more to maintain a $ rs $, recorded disjoint son $ x $ of the total number, if $ rs < = 1 $, there have been oolong, $ x $ is not a cut point, because $ x $ is not above section.

We return to this topic

We built a two-point a point in the artwork, a cut point to build a point, a point to which it is cut at the point they even double edge, thus forming a tree, and cut point represent the point, they the degree is not for the $ 1 $, if seen as rootless tree, they must put the border point on the boundary must be represented by two-point point.

We only consider the case built on the export of non-point cut, to $ 1 $ degree of representative points double points, we have to cut any of a non-point build an outlet.

For degree $> = points for double points 2 $, we can go through it on the other leaf spot, so do not build.

Another is that special consideration, China Unicom is the entire block shrunk to a solitary point, that is not a cut point, then we build two optional exit (a collapsed go to another)

If you consider that to be built on the export of cut points, the answer will not do better?

Originally degree on $> = $ 2 a point does not need to build, we do not consider.

Double leaf spot is to be built, and if we build on the cut point, when can a multiple use ah (funny), but in fact this is wrong. Because if a double leaf spot, only built on the cut point, then the cut point of collapse is no escape. . . . .

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<stack>
#define LL long long 
#define N 550
#define ri register int
using namespace std;

int dfn[N],low[N],cut[N];
int n,num,ctc,cc,T;
vector<int> to[N],c1[N],c2[N];
stack<int> s;
LL ans1,ans2;

void add_edge(int u,int v) {
  to[u].push_back(v); to[v].push_back(u);
}

void tarjan(int x,int ff) {
  dfn[x]=low[x]=++cc;
  s.push(x);
  
  int rs=0;
  for (ri i=0;i<to[x].size();i++) {
    int y=to[x][i];
    if (!dfn[y]) {
      tarjan(y,x);
      low[x]=min(low[x],low[y]);
      if (low[y]>=dfn[x]) {
        rs++;
        cut[x]=1;
        int t;
        num=ctc=0;
        while (1) {
          t=s.top(); s.pop();
          if (cut[t]) ++ctc; else ++num;
          if (t==y) break;
        }
        if (cut[x]) ++ctc; else ++num;
        c1[x].push_back(ctc); c2[x].push_back(num);
      }
    }
    else low[x]=min(low[x],dfn[y]);
  }
  
  if (x==ff && rs<=1) {
    for (ri i=0;i<c1[x].size();i++) c1[x][i]--,c2[x][i]++;
  }
  
  for (ri i=0;i<c1[x].size();i++) {
    if (c1[x][i]==0) {
      ans1+=2;
      ans2*=((c2[x][i]-1)*c2[x][i])/2;
    }
    else if (c1[x][i]==1) {
      ans1++;
      ans2*=c2[x][i];
    }
  }
}

int main() {
  freopen("mine1.in","r",stdin);
  int m,u,v;
  while (scanf("%d",&m)==1 && m) {
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(cut,0,sizeof(cut));
    for (ri i=1;i<=n;i++) to[i].clear(),c1[i].clear(),c2[i].clear();
    while (!s.empty()) s.pop();
    n=0; cc=0;
    ans1=0; ans2=1;
    for (ri i=1;i<=m;i++) {
      scanf("%d %d",&u,&v);
      add_edge(u,v);
      n=max(n,u);
      n=max(n,v);
    }
    for (ri i=1;i<=n;i++) if (!dfn[i]) tarjan(i,i);
    printf("Case %d: %lld %lld\n",++T,ans1,ans2);
  }
  return 0;
}

 

Guess you like

Origin www.cnblogs.com/shxnb666/p/11344735.html