您的位置:首页 > 其它

Codeforces 732F [边双联通分量][tarjan]

2016-10-19 21:56 537 查看
/*
不要低头,不要放弃,不要气馁,不要慌张
题意:
给一个无向图。现在要求给这个无向图的边加上方向。
定义f(x)为从x点出发能够到达的点的数目。
使得MIN(f(x))最大。

思路:
先tarjan找边双分量,然后从点数最大的边双分量开始dfs。
就酱。

中午老妈刚给我打电话问感冒没,我说没有,晚上就发烧了   gg
*/

#include<bits/stdc++.h>
#define N 400050
using namespace std;
int ednum;
struct edge{
int nn;
int id;
edge *next;
};
edge edges[N<<1];
edge *adj
;
struct st{
st(){}
st(int a,int b,int c){
s=a;e=b;xu=c;
}
int s,e,xu;
};
vector<st>ans;
inline void addedge(int a,int b,int c){
edge *tmp=&edges[ednum++];
tmp->id=b;
tmp->nn=c;
tmp->next=adj[a];
adj[a]=tmp;
}
int dfn
,low
,id
,s
,p,num,t,son
,nnm
;//dfn记录dfs时间戳
//low代表当前点到达的最小时间戳,id对点进行分组编号.num是时间戳
//s临时存储数据的手工栈,p栈顶元素的位置,son记录儿子因为无向图记录边都是两个边
void tarjan(int pos){
dfn[pos]=low[pos]=++num;
s[++p]=pos;
for(edge *it=adj[pos];it;it=it->next){
if(!dfn[it->id]){
son[pos]=it->id;
tarjan(it->id);
}
if(son[it->id]!=pos){
low[pos]=min(low[pos],low[it->id]);
}
}
if(low[pos]==dfn[pos]){
t++;
int y;
do{
nnm[t]++;
y=s[p--];
id[y]=t;
}while(y!=pos);
}
}
bool vis
;
bool vvis
;
void dfs(int pos){
vis[pos]=1;
for(edge *it=adj[pos];it;it=it->next){
if(!vis[it->id]){
son[pos]=it->id;
dfs(it->id);
}
if(son[it->id]!=pos&&!vvis[it->nn]){
vvis[it->nn]=1;
ans.push_back(st(pos,it->id,it->nn));
}
}
}
bool cmp(st a,st b){
return a.xu<b.xu;
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int a,b;
scanf("%d%d",&a,&b);
addedge(a,b,i);
addedge(b,a,i);
}
tarjan(1);
int pos,nnn=-1;
for(int i=1;i<=t;i++){
if(nnn<nnm[i]){
pos=i;
nnn=nnm[i];
}
}
printf("%d\n",nnn);
for(int i=1;i<=n;i++){
if(id[i]==pos){
memset(vis,0,sizeof(vis));
memset(son,0,sizeof(son));
dfs(i);
break;
}
}
sort(ans.begin(),ans.end(),cmp);
for(int i=0;i<ans.size();i++){
printf("%d %d\n",ans[i].e,ans[i].s);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: