边双连通分量。
这题有一点构造的味道。一个有向图,经过强连通缩点之后会形成一个有向无环图。
如果将最大的强连通分量放在顶端,其余的强连通分量都直接或间接指向他,那么这样就构造出了符合要求的图。
接下来就是要去寻找强连通分量。对于一个无向图来说,每一个边-双联通分量都可以将每条边定向之后构造成一个强连通分量,$dfs$一遍即可。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<ctime> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0),eps=1e-10; void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } template <class T> inline void read(T &x) { char c = getchar(); x = 0; while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar(); } } const int maxn = 800000 + 5; int n,m; int pre[maxn], dfs_clock, bcc_cnt; vector<int>G[maxn], bcc[maxn]; int belong[maxn],U[maxn],V[maxn],sz; int flag[maxn],ff[maxn],gg[maxn],ge[maxn],dd[maxn]; int Tarjan(int u,int fa) { int lowu=pre[u]=++dfs_clock; for(int i=0;i<G[u].size();i++) { int v=V[G[u][i]]; if(!pre[v]) { int lowv=Tarjan(v,u); lowu=min(lowu,lowv); if(lowv > pre[u]) ge[(G[u][i]+1)/2]=1; } else if(v!=fa) lowu=min(lowu,pre[v]); } return lowu; } void add(int a,int b) { sz++; U[sz]=a; V[sz]=b; G[a].push_back(sz); } void DFS(int x,int y) { flag[y]=1; for(int i=0;i<G[y].size();i++) { int v=V[G[y][i]]; if(v==x) continue; if(ff[(G[y][i]+1)/2]==1) continue; ff[(G[y][i]+1)/2]=1; gg[G[y][i]]=1; if(flag[v]==0) DFS(y,v); } } void dfs(int x) { belong[x]=bcc_cnt; for(int i=0;i<G[x].size();i++) { if(ge[(G[x][i]+1)/2]==1) continue; int v=V[G[x][i]]; if(belong[v]!=0) continue; dfs(v); } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } for (int i = 1; i <= n; i++) if (!pre[i]) Tarjan(i, -1); for(int i=1;i<=n;i++) { if(belong[i]!=0) continue; bcc_cnt++; dfs(i); } for(int i=1;i<=n;i++) dd[belong[i]]++; int mx=0,idx=0; for(int i=1;i<=bcc_cnt;i++) if(dd[i]>mx) mx=dd[i],idx=i; for(int i=1;i<=n;i++) if(belong[i]==idx) { DFS(-1,i); break; } printf("%d\n",mx); for(int i=1;i<=sz;i++) if(gg[i]) printf("%d %d\n",V[i],U[i]); return 0; }
时间: 2024-11-26 05:23:41