CF732F Tourist Reform(边双联通)

题意

在一张有向图中,设 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
",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
",u[i/2],v[i/2]);
 98         else printf("%d %d
",v[i/2],u[i/2]);
 99     }
100     return 0;
101 } 
View Code
原文地址:https://www.cnblogs.com/Xu-daxia/p/9385860.html