坑了我一天的题目。。跑了20ms挂了,就知道有个小毛病= =
无向图转有向图判强连通。
首先要知道什么样的无向图可以转化为强连通图?连通分量(环)自然是可以的;那么扩大范围(存在割顶),发现点连通分量也是可以的;再扩大范围(存在桥),明显不能满足。所以边连通分量是实现无向图与强连通图转化的界限。
那么如果原图本身不是边连通的呢?先缩点,问题转化为——怎样把无向无环图(森林)构建成边连通图:从度入手。其实真正要考虑的是叶子节点(degree==1),和部分根节点(degree==0或degree==1)。degree==0,需要加两条边;degree==1,一条;degree>=2,不需考虑。
注意:因为是有向边建图,每条边会加两次,所以s/2;但这样考虑还不完整,要(s+1)/2,附上一组数据。
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<stack> 5 #include<algorithm> 6 #define clr(a,m) memset(a,m,sizeof(a)) 7 #define ref(i,a,b) for(int i=a;i<=b;i++) 8 using namespace std; 9 10 const int MAXN=1111; 11 12 struct Edge{ 13 int v,next,vis; 14 Edge(){} 15 Edge(int _v,int _next):v(_v),next(_next),vis(0){} 16 }edge[MAXN*MAXN]; 17 18 int head[MAXN],tol; 19 int low[MAXN],pre[MAXN],bccno[MAXN],bcc_cnt,dfs_clock; 20 int dg[MAXN]; 21 22 stack<int>stk; 23 24 void init() 25 { 26 tol=0; 27 clr(head,-1); 28 } 29 30 void add(int u,int v) 31 { 32 edge[tol]=Edge(v,head[u]); 33 head[u]=tol++; 34 } 35 36 void dfs(int u) 37 { 38 int v; 39 pre[u]=low[u]=++dfs_clock; 40 stk.push(u); 41 for(int i=head[u];i!=-1;i=edge[i].next){ 42 if(edge[i].vis) 43 continue; 44 edge[i].vis=edge[i^1].vis=1; 45 46 v=edge[i].v; 47 if(!pre[v]){ 48 dfs(v); 49 low[u]=min(low[u],low[v]); 50 }else if(!bccno[v]) 51 low[u]=min(low[u],pre[v]); 52 } 53 if(pre[u]==low[u]){ 54 bcc_cnt++; 55 do{ 56 v=stk.top(); 57 stk.pop(); 58 bccno[v]=bcc_cnt; 59 }while(u!=v); 60 } 61 } 62 63 void find_bcc(int n) 64 { 65 dfs_clock=bcc_cnt=0; 66 memset(pre,0,sizeof(pre)); 67 memset(bccno,0,sizeof(bccno)); 68 69 ref(i,0,n-1) 70 if(!pre[i]) 71 dfs(i); 72 } 73 74 int main() 75 { 76 int n,m,u,v; 77 while(~scanf("%d%d",&n,&m)) 78 { 79 init(); 80 ref(i,0,m-1){ 81 scanf("%d%d",&u,&v); 82 u--;v--; 83 add(u,v); 84 add(v,u); 85 } 86 find_bcc(n); 87 memset(dg,0,sizeof(dg)); 88 ref(i,0,n-1){ 89 for(int j=head[i];j!=-1;j=edge[j].next) 90 { 91 int v=edge[j].v; 92 if(bccno[i]!=bccno[v]){ 93 dg[bccno[i]]++; 94 dg[bccno[v]]++; 95 } 96 } 97 } 98 int s=0; 99 ref(i,1,bcc_cnt){ 100 if(dg[i]/2==1) 101 s+=1; 102 else if(!dg[i]) 103 s+=2; 104 } 105 if(bcc_cnt==1)printf("0 "); 106 else printf("%d ",(s+1)/2); 107 } 108 return 0; 109 } 110 /* 111 3 3 112 1 2 2 3 3 1 113 114 10 12 115 1 2 116 2 3 117 3 4 118 4 2 119 1 5 120 5 6 121 6 7 122 7 5 123 1 8 124 8 9 125 9 10 126 10 8 127 */