CF732 F Tourist Reform——边双连通分量
Posted zinn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF732 F Tourist Reform——边双连通分量相关的知识,希望对你有一定的参考价值。
题目:http://codeforces.com/contest/732/problem/F
首先把边双缩点,边双内部 dfs 一个顺序一定是可以从每个点走到边双内部所有点的,因为它是以环为基本单位;
然后对于缩点之后的图,找到 siz 最大的点作为根 dfs,再连反边,那么只有 siz 最大的那个点只能走到自己内部,就可以使答案最大;
结构体要开得精细一点,防止爆空间?还是什么奇奇怪怪的错误之类的...
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const maxn=4e5+5; int n,m,hd[maxn],ct=1,cnt=1,dfn[maxn],low[maxn],tim,col[maxn],cr,siz[maxn]; int sta[maxn],top,head[maxn]; bool vis[maxn]; //struct N{ // int to,nxt,bh,u,v,f; // N(int t=0,int n=0,int b=0):to(t),nxt(n),bh(b) {} //}ed[maxn<<1],e[maxn],edge[maxn<<1];//这样写会爆空间?! struct N{ int to,nxt,bh; N(int t=0,int n=0,int b=0):to(t),nxt(n),bh(b) {} }ed[maxn<<1],edge[maxn<<1]; struct E{int u,v,f;}e[maxn]; void add(int x,int y,int b){ed[++ct]=N(y,hd[x],b); hd[x]=ct;} void add2(int x,int y,int b){edge[++cnt]=N(y,head[x],b); head[x]=cnt;} void tarjan(int x,int f) { dfn[x]=low[x]=++tim; vis[x]=1; sta[++top]=x; for(int i=hd[x];i;i=ed[i].nxt) { int u=ed[i].to; if(u==f)continue; if(!dfn[u]) tarjan(u,x),low[x]=min(low[x],low[u]); else if(vis[u]) low[x]=min(low[x],dfn[u]); } if(dfn[x]==low[x]) { cr++; while(sta[top]!=x) { int y=sta[top]; top--; vis[y]=0; col[y]=cr; siz[cr]++; } top--; vis[x]=0; col[x]=cr; siz[cr]++; } } void dfs(int x) { vis[x]=1; for(int i=head[x],u,eg;i;i=edge[i].nxt) { if(vis[u=edge[i].to])continue; if(x==col[e[eg=edge[i].bh].u]) e[eg].f=0; else e[eg].f=1; dfs(u); } } void dfs2(int x) { vis[x]=1; for(int i=hd[x],u,eg;i;i=ed[i].nxt) { u=ed[i].to; if(col[u]!=col[x])continue; if(x==e[eg=ed[i].bh].u) e[eg].f=1; else e[eg].f=0; if(!vis[u])dfs2(u); } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&e[i].u,&e[i].v); add(e[i].u,e[i].v,i); add(e[i].v,e[i].u,i); } for(int i=1;i<=n;i++) if(!dfn[i])tarjan(i,0); memset(vis,0,sizeof vis); for(int i=1;i<=n;i++) if(!vis[i])dfs2(i); for(int i=1,u,v;i<=ct;i++) if((u=col[ed[i].to])!=(v=col[ed[i^1].to]))add2(u,v,ed[i].bh),add2(v,u,ed[i].bh); int rt=0,mx=0; for(int i=1;i<=cr;i++) if(siz[i]>mx)mx=siz[i],rt=i; printf("%d ",mx); memset(vis,0,sizeof vis); dfs(rt); for(int i=1;i<=m;i++) { if(e[i].f==1)printf("%d %d ",e[i].u,e[i].v); else printf("%d %d ",e[i].v,e[i].u); } return 0; }
以上是关于CF732 F Tourist Reform——边双连通分量的主要内容,如果未能解决你的问题,请参考以下文章
codeforces CF732F Tourist Reform Tarjan边双连通分量
CF 732F Tourist Reform——v-SCC+dfs
CodeForces 732F Tourist Reform