Codeforces 732F
题意:
给出一个无向图,要求将每条边确定一个方向,使新图中所有点能到达的点的数目最小值最大。
考虑求出边双连通分量和割边,在缩点后的图中,我们贪心的令每一条割边指向点数目最多的边双。
对于每一个边双,我们可以用dfs确定边的方向使其在新图中变成连通分量。
最小值为点数最多的边双的点数。
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #include <math.h> 6 using namespace std; 7 #define maxn 400010 8 #define pa pair<int,int> 9 template<typename __> 10 inline void read(__ &s) 11 { 12 char ch; 13 for(ch=getchar(),s=0;ch<'0'||ch>'9';ch=getchar()); 14 for(;ch>='0'&&ch<='9';ch=getchar()) 15 s=s*10+ch-'0'; 16 } 17 int n,m; 18 struct edge 19 { 20 int v,id,nex; 21 }e[maxn<<1]; 22 int pr[maxn],cnt; 23 int st[maxn],top; 24 int mx,root; 25 int low[maxn],dfn[maxn]; 26 int bcc_dfn; 27 pa ans[maxn]; 28 void add(int u,int v,int id) 29 { 30 e[++cnt]=(edge){v,id,pr[u]}; 31 pr[u]=cnt; 32 e[++cnt]=(edge){u,id,pr[v]}; 33 pr[v]=cnt; 34 } 35 void tarjan(int u,int f) 36 { 37 low[u]=dfn[u]=++bcc_dfn; 38 st[++top]=u; 39 for(int i=pr[u];i;i=e[i].nex) 40 { 41 int v=e[i].v; 42 if(v==f) 43 continue; 44 if(!dfn[v]) 45 { 46 ans[e[i].id]=pa(v,u); 47 tarjan(v,u); 48 low[u]=min(low[u],low[v]); 49 } 50 else 51 { 52 ans[e[i].id]=pa(u,v); 53 low[u]=min(low[u],dfn[v]); 54 } 55 } 56 if(low[u]==dfn[u]) 57 { 58 int siz=0; 59 int v=-1; 60 while(v!=u) 61 { 62 v=st[top--]; 63 siz++; 64 } 65 if(siz>mx) 66 { 67 mx=siz; 68 root=u; 69 } 70 } 71 } 72 int main() 73 { 74 read(n); 75 read(m); 76 int u,v; 77 for(int i=1;i<=m;i++) 78 { 79 read(u); 80 read(v); 81 add(u,v,i); 82 } 83 mx=0; 84 tarjan(1,-1); 85 memset(dfn,0,sizeof(dfn)); 86 bcc_dfn=0; 87 mx=0; 88 tarjan(root,-1); 89 printf("%d\n",mx); 90 for(int i=1;i<=m;i++) 91 printf("%d %d\n",ans[i].first,ans[i].second); 92 }