tarjan——点双连通分量

简介:用tarjan找割点,当dfn[u]<=low[v]时,证明当前的u为割点,注意割点可能存在于多个点双连通分量中,所以存点的时候要格外注意。如果当前遍历到的v已在栈中,可以用dfn[v]更新low[u]。

  ps:两点一边的图也为一个点双连通分量。

模板:

  将下面的代码略微改动即可

例题:

  hduoj3394  Railway

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<vector>
 5 #define numm ch-48
 6 #define pd putchar(' ')
 7 #define pn putchar('\n')
 8 #define pb push_back
 9 #define debug(args...) cout<<#args<<"->"<<args<<endl
10 #define bug cout<<"************"
11 using namespace std;
12 template <typename T>
13 void read(T &res) {
14     bool flag=false;char ch;
15     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
16     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
17     flag&&(res=-res);
18 }
19 template <typename T>
20 void write(T x) {
21     if(x<0) putchar('-'),x=-x;
22     if(x>9) write(x/10);
23     putchar(x%10+'0');
24 }
25 typedef long long ll;
26 const int maxn=10010;
27 const int maxm=200010;
28 const ll mod=1e9+7;
29 int low[maxn],dfn[maxn],sta[maxn],vis[maxn],sum,head[maxn],f[maxn];
30 int u[maxm],v[maxm];
31 int n,m,lay,ans1,ans2,cnt;
32 struct node {
33     int net,v;
34     node(){}
35     node(int v,int net):v(v),net(net){}
36 }e[maxm];
37 void add(int u,int v) {
38     e[++cnt]=node(v,head[u]);
39     head[u]=cnt;
40 }
41 void getnode(int sccnum) {
42     int cnt=0;
43     for(int i=1;i<=m;i++)
44         if(f[u[i]]==sccnum&&f[u[i]]==f[v[i]])
45             cnt++;
46     if(cnt>=sum) ans1+=cnt;  ///当中没有桥
47     if(cnt>sum) ans2+=cnt;
48 }
49 void tarjan(int x,int &sccnum) {
50     sta[++cnt]=x;
51     low[x]=lay;
52     dfn[x]=lay++;
53     vis[x]=1;
54     for(int i=head[x];~i;i=e[i].net) {
55         int v=e[i].v;
56         if(!dfn[v]) {
57             tarjan(v,sccnum);
58             low[x]=min(low[x],low[v]);
59             if(dfn[x]<=low[v]) {    ///x是割点
60                 ++sccnum;
61                 sum=0;  ///点的数量
62                 do {
63                     f[sta[cnt]]=sccnum;
64                     vis[sta[cnt]]=2;
65                     sum++;
66                 }while(sta[cnt--]!=v);
67                 f[x]=sccnum,sum++;
68                 getnode(sccnum);
69             }
70         }
71         else if(vis[v]==1) low[x]=min(low[x],dfn[v]);
72     }
73 }
74 int main()
75 {
76 
77     while(scanf("%d%d",&n,&m)!=EOF&&(n+m)) {
78         ans1=ans2=0;
79         for(int i=0;i<n;i++)
80             head[i]=-1,vis[i]=0,dfn[i]=0,f[i]=0;
81         cnt=0;
82         for(int i=1;i<=m;i++) {
83             read(u[i]),read(v[i]);
84             add(u[i],v[i]);
85             add(v[i],u[i]);
86         }
87         lay=1,cnt=0;
88         int sccnum=0;
89         for(int i=0;i<n;i++)
90             if(!vis[i]) tarjan(i,sccnum);
91         write(m-ans1),pd,write(ans2);pn;
92     }
93     return 0;
94 }
View Code

猜你喜欢

转载自www.cnblogs.com/wuliking/p/11514857.html
今日推荐