【题意】:
链接:codeforces 732F Tourist Reform
n个点,m条边,v[ i ]表示从点 i 出发,到达的不同地方的数量。一开始是无向边,让你把每条边改成有向边,怎么改,可以使得最小的v[ i ]最大。
【题解】:
我们考虑如果这个图中存在桥,即把这条边去掉,这个图就不能连通,那么这条边是关键的。所以我们用tarjan对整个图搜一遍,找到双连通分量和桥,把是桥的边标记一下,然后重新建图。根据边双连通分量的定义,我们可以知道,重新建的图,是一棵树。
那么我们只要把v[ i ]最大的点,当作树的根,这样其他所有的点往父亲连,就会让最小的v最大。
【代码】:
#include<stdio.h>
#include<math.h>
#include<vector>
#include<string.h>
#include<queue>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
struct Node
{
int u,v,w,nxt,vis,flag;
}node[800005],node2[800005];
int cnt=0,cnt2=0,head[400005],head2[400005],index,top,bccnum;
int dfn[400005],low[400005],st[400005],bcc[400005],siz[400005];
void build(int u,int v)
{
node[cnt].u=u;
node[cnt].v=v;
node[cnt].w=0;
node[cnt].vis=0;
node[cnt].flag=0;
node[cnt].nxt=head[u];
head[u]=cnt++;
}
void build2(int u,int v)
{
node2[cnt2].u=u;
node2[cnt2].v=v;
node2[cnt2].w=0;
node2[cnt2].vis=0;
node2[cnt2].flag=0;
node2[cnt2].nxt=head2[u];
head2[u]=cnt2++;
}
void tarjan(int rt)
{
dfn[rt]=low[rt]=++index;
st[++top]=rt;
for(int i=head[rt];~i;i=node[i].nxt){
int v=node[i].v;
if(node[i].vis==1) continue;
node[i].vis=node[i^1].vis=1;
node[i].flag=1;
if(!dfn[v]){
tarjan(v);
low[rt]=min(low[rt],low[v]);
if(dfn[rt]<low[v]){
node[i].w=node[i^1].w=1;
}
}
else if(low[rt]>dfn[v]){
node[i].flag=1;
low[rt]=dfn[v];
}
}
if(low[rt]==dfn[rt]){
bccnum++;
while(1){
int x=st[top--];
bcc[x]=bccnum;
siz[bccnum]++;
if(x==rt) break;
}
}
}
map<int,int> mp;
void dfs(int rt,int f)
{
mp[rt]=f;
for(int i=head2[rt];~i;i=node2[i].nxt){
int v=node2[i].v;
if(v!=f){
dfs(v,rt);
}
}
}
int main(void)
{
int n,m,u,v;
while(~scanf("%d%d",&n,&m)){
memset(head,-1,sizeof(head));
memset(head2,-1,sizeof(head2));
memset(dfn,0,sizeof(dfn));
memset(siz,0,sizeof(siz));
mp.clear();
for(int i=0;i<m;i++){
scanf("%d%d",&u,&v);
build(u,v);
build(v,u);
}
index=0;top=0;bccnum=0;
tarjan(1);
int mark,maxn=-1;
//printf("%d\n",bccnum);
for(int i=0;i<cnt;i++){
if(siz[bcc[node[i].u]]>maxn){
maxn=siz[bcc[node[i].u]];
}
if(node[i].w==1){
build2(bcc[node[i].u],bcc[node[i].v]);
if(siz[bcc[node[i].u]]==maxn){
mark=bcc[node[i].u];
}
}
}
//printf("Start dfs\n");
printf("%d\n",maxn);
dfs(mark,-1);
for(int i=0;i<cnt;i++){
if(node[i].flag==0&&node[i^1].flag==0){
printf("%d %d\n",node[i].u,node[i].v);
node[i].flag=1;
i++;
continue;
}
if(node[i].w==1){
if(mp[bcc[node[i].u]]==bcc[node[i].v]){
printf("%d %d\n",node[i].u,node[i].v);
}
}
else{
if(node[i].flag==1){
printf("%d %d\n",node[i].u,node[i].v);
}
}
}
}
return 0;
}