题意
在一张有向图中,设 ri 为从点 i 出发能够到达的点的数量。
定义有向图的“改良值”为 ri 的最小值。
现给出一张无向图,要求给每条边定一个方向,使产生的有向图“改良值”最大。
输出 最大改良值和边的方向。
n,m≤400000
题解
对于无向图的每个“边双连通分量”,一定存在一种定向方法,使其改良值等于其大小
把无向图缩点后,以最大的 e-DCC 为零出度点(终点) BFS 定向
每个 e-DCC 内部 DFS 定向
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstdio> 6 #include<queue> 7 using namespace std; 8 int const N=400100; 9 int head[N],cnt; 10 int dfn[N],low[N],tot,flag[N*2]; 11 int c[N],t[N]; 12 int vis[N]; 13 int n,m,u[N],v[N],w[N],num; 14 struct edge{ 15 int to,nxt,flag; 16 }e[N*3]; 17 void add(int u,int v){ 18 cnt++; 19 e[cnt].nxt=head[u]; 20 e[cnt].to=v; 21 head[u]=cnt; 22 } 23 void Tarjan(int u,int from){ 24 dfn[u]=low[u]=++tot; 25 for(int i=head[u];i;i=e[i].nxt){ 26 int v=e[i].to; 27 if(!dfn[v]){ 28 Tarjan(v,i); 29 if(e[i].flag==0&&e[i^1].flag==0)e[i].flag=1; 30 low[u]=min(low[u],low[v]); 31 if(dfn[u]<low[v]){ 32 flag[i]=flag[i^1]=1; 33 e[i].flag=e[i^1].flag=0; 34 } 35 } 36 else if(i!=(from^1)){ 37 if(e[i].flag==0&&e[i^1].flag==0)e[i].flag=1; 38 low[u]=min(low[u],dfn[v]); 39 } 40 } 41 } 42 void bfs(int u,int col){ 43 queue<int> q; 44 q.push(u); 45 c[u]=col; 46 t[col]=1; 47 while(!q.empty()){ 48 int u=q.front(); 49 q.pop(); 50 for(int i=head[u];i;i=e[i].nxt){ 51 int v=e[i].to; 52 if(c[v]||flag[i])continue; 53 c[v]=col; 54 t[col]++; 55 q.push(v); 56 } 57 } 58 } 59 void dfs(int u){ 60 vis[u]=1; 61 for(int i=head[u];i;i=e[i].nxt){ 62 int v=e[i].to; 63 if(vis[v]==0){ 64 if(c[u]!=c[v])e[i].flag=1; 65 dfs(v); 66 } 67 } 68 } 69 int main(){ 70 scanf("%d%d",&n,&m); 71 cnt=1; 72 for(int i=1;i<=m;i++){ 73 scanf("%d%d",&u[i],&v[i]); 74 add(u[i],v[i]); 75 add(v[i],u[i]); 76 } 77 Tarjan(1,0); 78 int maxx=0,s; 79 for(int i=1;i<=n;i++){ 80 if(!c[i])bfs(i,++num); 81 if(t[num]>maxx){ 82 maxx=t[num]; 83 s=num; 84 } 85 } 86 printf("%d\n",maxx); 87 for(int i=1;i<=n;i++){ 88 if(c[u[i]]==c[v[i]])continue; 89 } 90 for(int i=1;i<=n;i++){ 91 if(!vis[i]&&c[i]==s){ 92 dfs(i); 93 break; 94 } 95 } 96 for(int i=2;i<=cnt;i+=2){ 97 if(e[i].flag==0)printf("%d %d\n",u[i/2],v[i/2]); 98 else printf("%d %d\n",v[i/2],u[i/2]); 99 } 100 return 0; 101 }