作为一道板子题放在第二题令人身心愉悦,不到一个小时码完连对拍都没打。
关于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.中的判断条件有>=;
4.多测清空!!!!!!!!!!!!!!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 ",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 }