1. 程式人生 > >CodeForces 732F. Tourist Reform 邊雙聯通分量

CodeForces 732F. Tourist Reform 邊雙聯通分量

題目連結:http://codeforces.com/problemset/problem/732/F

題意:

       給你一個無向連通圖,要你把這個圖的邊變成有向邊,使得每個點能到達的點數最大,按順序輸出每條邊的連向。

做法:

       有點繞吧聽著,每個點都能達到的點最大的話,最好的就是相互都能到達,那麼我們自然的就想到強連通分量,一個強聯通分量內的點可以相互到達,當然這道題因為是無向圖,所以就是邊雙連通分量了,那麼對於不同分量的點呢?因為我們要使得每個點都能到的點最大,如果我們把大的分量的點指向小的,那麼很明顯,最大的就是那個小的了,所以我們就要把邊的朝向都指向那個最大的強連通分量。這裡有個小優化,如果搜尋的時候在一個強連通分量內的話,那麼就正常朝向,否則取反向邊(因為我們要讓所有的點都能指向那個最大的分量)

 


#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=400005;
struct node{
    int from,to,next;
}e[maxn<<1];
stack<int> sa;
int now,head[maxn],bccsum[maxn],bccnum,mark[maxn];
int dfn[maxn],low[maxn],belong[maxn],n,m,cnt,vis[maxn<<1];
bool las[maxn];
void add(int u,int v){
    e[now].from=u,e[now].to=v;
    e[now].next=head[u],head[u]=now++;
}
void tarjan(int x,int fa){
    dfn[x]=low[x]=++cnt;
    sa.push(x);
    for(int i=head[x];~i;i=e[i].next){
        int v=e[i].to;
        if(v==fa) continue;
        if(!dfn[v]){
            tarjan(v,x);
            low[x]=min(low[x],low[v]);
        }
        else if(!belong[v]) low[x]=min(low[x],low[v]);
    }
    if(dfn[x]==low[x]){
        bccnum++;
        bccsum[bccnum]=0;
        while(1){
            int u=sa.top();sa.pop();
            belong[u]=bccnum;
            bccsum[bccnum]++;
            if(u==x) break;
        }
    }
}
void dfs(int now){
    las[now]=1;
    for(int i=head[now];~i;i=e[i].next){
        int v=e[i].to;
        if(vis[i]!=0) continue;
        if(belong[v]==belong[now]){
            vis[i]=1; vis[i^1]=-1;
        }
        else vis[i^1]=1,vis[i]=-1;
        if(!las[v]) dfs(v);
    }
}
void init(){
    memset(head,-1,sizeof(head)); now=0; cnt=0;
    bccnum=0; memset(mark,0,sizeof(mark)); memset(las,0,sizeof(las));
    memset(dfn,0,sizeof(dfn)); memset(vis,0,sizeof(vis));
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        if(n==0&&m==0) break;
        int u,v;
        init();
        for(int i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            add(u,v); add(v,u);
        }
        tarjan(1,1);
        int root=1;
        for(int i=2;i<=n;i++){
            if(bccsum[belong[i]]>bccsum[belong[root]]){
                root=i;
            }
        }
        dfs(root);
        printf("%d\n",bccsum[belong[root]]);
        for(int i=0;i<now;i+=2){
            if(vis[i]==1) printf("%d %d\n",e[i].from,e[i].to);
            else printf("%d %d\n",e[i^1].from,e[i^1].to);
        }
    }
	return 0;
}