回家(tarjan V-DCC点双连通分量的求法及缩点 求割点)模板题

作为一道板子题放在第二题令人身心愉悦,不到一个小时码完连对拍都没打。

关于tarjan割点的注意事项:

1.在该板子中我们求的是V-DCC,而不是缩点,V-DCC最少有两个点组成,表示出掉一个块里的任意

一点及其连边,联通性不变,所以割点只是顺便标记上low[to]>=dfn[x]的点,在以后的操作中

将割点与联通块连边,所以最坏情况下所生点数(即原图为一条链)为2*n-2

边数的话如没有明确给出一般为点数的8倍。

******(这题80分,就是数组开小,没加快读)*******

2.我们在tarjan中每次分联通块时,while(top!=to),因为x可以属于多个联通块,所以我们

不能将其弹栈,但可以将其放进块中

3.else中low用dfn更新,因为不这样我们会将所有节点更新为1,这里不需要判断to是否为fa

因为2.中的判断条件有>=;

扫描二维码关注公众号,回复: 6872266 查看本文章

4.多测清空!!!!!!!!!!!!!!

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 #include<algorithm>
  6 #include<cmath>
  7 #include<stack>
  8 #include<map>
  9 #include<queue>
 10 #define ps push_back
 11 #define MAXN 405101
 12 #define ll long long
 13 using namespace std;
 14 int read()
 15 {
 16    char c=getchar();int x=0;
 17    while(c<'0'||c>'9')
 18    {
 19         c=getchar();
 20    }
 21    while(c>='0'&&c<='9')
 22    {
 23       x=(x<<1)+(x<<3)+(c^48);
 24       c=getchar();
 25    }
 26    return x;
 27 }
 28 int dfn[MAXN],low[MAXN],cut[MAXN],de;
 29 int vis[MAXN];
 30 int num_id,cnt;
 31 int belong[MAXN];
 32 vector<int>v[MAXN];
 33 stack<int>q;
 34 struct node{int to,n;}e1[MAXN*4],e2[MAXN*4];
 35 int head1[MAXN],head2[MAXN];int tot1,tot2;
 36 void add1(int u,int v)
 37 {
 38     e1[++tot1].to=v;e1[tot1].n=head1[u];head1[u]=tot1;
 39 }
 40 void add2(int u,int v)
 41 {
 42     e2[++tot2].to=v;e2[tot2].n=head2[u];head2[u]=tot2;
 43 }
 44 void tarjan(int x)
 45 {
 46    dfn[x]=low[x]=++de;vis[x]=1;q.push(x);
 47    int ss=0;
 48    for(int i=head1[x];i;i=e1[i].n)
 49    {
 50       int to=e1[i].to;
 51       if(dfn[to]==0)
 52       {         
 53           tarjan(to);
 54           low[x]=min(low[x],low[to]);
 55           if(low[to]>=dfn[x])
 56           {
 57               ss++;
 58               if(x!=1||ss>1)
 59               {
 60                   cut[x]=1;  
 61               }
 62               cnt++;
 63               int top=0;
 64               do
 65               {
 66                   top=q.top();q.pop();vis[to]=0;
 67                   v[cnt].ps(top);
 68               }
 69               while(to!=top);
 70               v[cnt].ps(x);
 71           }
 72       }  
 73       else 
 74           low[x]=min(low[x],dfn[to]);
 75    }
 76 }
 77 int n;
 78 int cut_kuan[MAXN];
 79 void init()
 80 {
 81     num_id=cnt;
 82     for(int i=1;i<=n;++i)
 83     {
 84         if(cut[i]==1)
 85         {
 86             belong[i]=++num_id;
 87             cut_kuan[num_id]=i;  
 88         }
 89     }
 90     for(int x=1;x<=cnt;++x)
 91     {
 92         for(int i=0;i<v[x].size();++i)
 93         {
 94             int now=v[x][i];
 95             if(cut[now]==1)
 96             {
 97                 add2(belong[now],x);
 98                 add2(x,belong[now]);
 99             }
100             else 
101             {
102                 belong[now]=x;
103             }
104         }
105     }
106 }
107 bool bian[MAXN];int fa[MAXN];
108 void DFS(int x)
109 {
110    bian[x]=1;
111    for(int i=head2[x];i;i=e2[i].n)
112    {
113        int to=e2[i].to;
114        if(bian[to]==1)continue;
115        fa[to]=x;
116        DFS(to);
117    }
118 }
119 int ans[MAXN];
120 void find()
121 {
122     int x=belong[n];
123     while(fa[x]!=0)
124     {
125         x=fa[x];
126         if(cut_kuan[x]!=0&&x!=belong[1])
127         {
128            ans[++ans[0]]=cut_kuan[x];
129         }
130     }
131 }
132 int T,m;
133 int main()
134 {
135     scanf("%d",&T);
136     while(T--)
137     {
138          memset(head1,0,sizeof(head1));
139          memset(head2,0,sizeof(head2));
140          memset(cut,0,sizeof(cut));
141          memset(dfn,0,sizeof(dfn));
142          memset(low,0,sizeof(low));
143          memset(vis,0,sizeof(vis));
144          memset(belong,0,sizeof(belong));
145          memset(fa,0,sizeof(fa));
146          memset(bian,0,sizeof(bian));
147          memset(ans,0,sizeof(ans));
148          memset(cut_kuan,0,sizeof(cut_kuan));
149          tot1=0;tot2=0;
150          n=read();m=read();
151          for(int i=1;i<=m;++i)
152          {
153              int x,y;
154              //scanf("%d%d",&x,&y);
155              x=read();y=read();
156              add1(x,y);add1(y,x); 
157          }
158          tarjan(1);
159          init();
160          DFS(belong[1]);
161          find();
162          printf("%d\n",ans[0]);
163          sort(ans+1,ans+ans[0]+1);
164          for(int i=1;i<=ans[0];++i)
165          {
166              printf("%d ",ans[i]);
167          }
168          cout<<endl;
169          for(int i=1;i<=cnt;++i)
170          {
171              v[i].clear();
172          }
173          cnt=0;de=0;num_id=0;
174     }
175 }
View Code

猜你喜欢

转载自www.cnblogs.com/Wwb123/p/11248077.html