codeforces 732F 双联通分量

来源:互联网 发布:小米note 顶配版我知乎 编辑:程序博客网 时间:2024/06/06 21:02

点击打开链接

题意:给一个无向图,现在将所有的边变为有向,使得每个点可以到达的点的个数的最小值最大,然后将变好的有向图输出

思路:可以知道无向图时在一个连通分量中的点是可以做到互达的,也就是这个联通分量里的点可以变成有向的联通分量,那么现在的图就是一个由好多个连通分量组成的一个树,然后对于割边来说,只有确定它的方向才能找出那个最小值,因为割边为有向了,所以所有的联通块肯定都是指向最大的那个联通块才能达到要求,画个图看一下即可,然后剩下的工作就是将无向的联通块的边变为有向,用一个dfs搜一下就行了

#include <queue>#include <vector>#include <stdio.h>#include <string.h>#include <stdlib.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const ll INF=0x3f3f3f3f3f3f3f3fll;const int maxn=400010;struct edge{    int to,flag,rev,id;    edge(int a,int b,int c,int d){to=a;flag=b;rev=c;id=d;}};vector<edge>G[maxn];int L[maxn],E[maxn],vis[maxn],stack1[maxn];int n,m,k,kk;void dfs(int x,int fa){    vis[x]=1;L[x]=k;E[x]=k++;stack1[kk++]=x;    int flag=0;    for(unsigned int i=0;i<G[x].size();i++){        edge e=G[x][i];        if(e.to!=fa){            if(!vis[e.to]){                dfs(e.to,x);                L[x]=min(L[x],L[e.to]);            }else L[x]=min(L[x],E[e.to]);        }else{            if(flag) L[x]=min(L[x],E[e.to]);            flag++;        }    }    if(L[x]==E[x]){        while(stack1[kk]!=x&&kk>0){            L[stack1[kk-1]]=L[x];            kk--;            vis[stack1[kk]]=0;        }    }}void tarjan(){    memset(L,0,sizeof(L));    memset(E,0,sizeof(E));    memset(stack1,0,sizeof(stack1));    kk=0;k=1;dfs(1,1);}int U[maxn],V[maxn],val[maxn],fans[maxn][2];void fdfs(int x,int fa){    for(unsigned int i=0;i<G[x].size();i++){        edge t=G[x][i];        if(t.flag||t.to==fa) continue;        G[t.to][t.rev].flag=1;        G[x][i].flag=1;        if(L[x]!=L[t.to]){            fans[t.id][0]=t.to,fans[t.id][1]=x;            fdfs(t.to,x);        }else{            fans[t.id][0]=x;fans[t.id][1]=t.to;            fdfs(t.to,x);        }    }}int main(){    while(scanf("%d%d",&n,&m)!=-1){        for(int i=0;i<=n;i++){            G[i].clear();vis[i]=0;val[i]=0;        }        for(int i=1;i<=m;i++){            scanf("%d%d",&U[i],&V[i]);            G[U[i]].push_back(edge(V[i],0,G[V[i]].size(),i));            G[V[i]].push_back(edge(U[i],0,G[U[i]].size()-1,i));        }        tarjan();        for(int i=1;i<=n;i++) val[L[i]]++;        int max1=0,fpos;        for(int i=1;i<=n;i++) if(val[i]>max1) max1=val[i],fpos=i;        printf("%d\n",max1);        for(int i=1;i<=n;i++) if(L[i]==fpos){fdfs(i,0);break;}        for(int i=1;i<=m;i++) printf("%d %d\n",fans[i][0],fans[i][1]);    }    return 0;}

0 0