1. 程式人生 > >Railway HDU - 3394 (點雙連通)

Railway HDU - 3394 (點雙連通)

struct bre bool cnblogs n) pri vector namespace origin

Railway

HDU - 3394

題意:一個無向圖,1求不在任何一個環裏的邊數;2求在不止一個環裏的邊數。

第一問明顯就是求橋,第二問,如果求出的某個點雙連通分量裏面邊數多於點數,說明不止一個環,那麽所有的邊都在不止一個環裏。

該求點雙連通的,,求成了邊雙連通。。。要仔細分析問題。

技術分享
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 using namespace std;
 6 const int maxv=10010
; 7 int n,m; 8 int ans1,ans2; 9 struct Edge{ 10 int u,v,nex; 11 bool iscut; 12 }e[100010<<1]; 13 int head[maxv]; 14 int cnt; 15 void init(){ 16 memset(head,-1,sizeof(head)); 17 cnt=0; 18 } 19 void add(int u,int v){ 20 e[cnt].u=u; 21 e[cnt].iscut=0; 22 e[cnt].v=v; 23 e[cnt].nex=head[u];
24 head[u]=cnt++; 25 } 26 int pre[maxv],bccno[maxv],dfsk,bcc_cnt; 27 int vis[maxv]; 28 vector<int> bcc[maxv]; 29 30 int dfs(int u,int id){ 31 int lowu=pre[u]=++dfsk; 32 for(int i=head[u];i!=-1;i=e[i].nex){ 33 int v=e[i].v; 34 if(i==(id^1)) continue; 35 if(!pre[v]){
36 int lowv=dfs(v,i); 37 lowu=min(lowu,lowv); 38 if(lowv>pre[u]) e[i].iscut=e[i^1].iscut=1,ans1++; 39 } 40 else lowu=min(lowu,pre[v]); 41 } 42 return lowu; 43 } 44 void dfs1(int u){ 45 bccno[u]=bcc_cnt; 46 vis[u]=1; 47 for(int i=head[u];i!=-1;i=e[i].nex){ 48 if(e[i].iscut) continue; 49 bcc[bcc_cnt].push_back(i); 50 int v=e[i].v; 51 if(!vis[v]) dfs1(v); 52 } 53 } 54 55 void find_bcc(int n){ 56 memset(pre,0,sizeof(pre)); 57 memset(vis,0,sizeof(vis)); 58 memset(bccno,0,sizeof(bccno)); 59 dfsk=bcc_cnt=0; 60 for(int i=0;i<n;i++) if(!pre[i]) dfs(i,-1); 61 for(int i=0;i<n;i++) if(!vis[i]){ 62 bcc_cnt++; 63 bcc[bcc_cnt].clear(); 64 dfs1(i); 65 } 66 } 67 int main(){ 68 while(scanf("%d%d",&n,&m)&&(n||m)){ 69 init(); 70 ans1=ans2=0; 71 int u,v; 72 for(int i=0;i<m;i++){ 73 scanf("%d%d",&u,&v); 74 add(u,v); 75 add(v,u); 76 } 77 find_bcc(n); 78 79 for(int i=1;i<=bcc_cnt;i++){ 80 int temp=0; 81 memset(vis,0,sizeof(vis)); 82 // cout<<bcc[i].size()<<endl; 83 for(int j=0;j<bcc[i].size();j++){ 84 // printf("---%d---\n",bcc[i][j]); 85 Edge p=e[bcc[i][j]]; 86 if(!vis[p.u]) {vis[p.u]=1;temp++;} 87 if(!vis[p.v]) {vis[p.v]=1;temp++;} 88 } 89 if(temp<bcc[i].size()/2) ans2+=bcc[i].size()/2; 90 } 91 printf("%d %d\n",ans1,ans2); 92 } 93 }
邊雙連通=_= 技術分享
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <vector>
  5 #include <stack>
  6 using namespace std;
  7 const int maxv=10010;
  8 int n,m;
  9 int ans1,ans2;
 10 struct Edge
 11 {
 12     int u,v,nex;
 13 }e[100010<<1];
 14 int head[maxv];
 15 int cnt;
 16 void init()
 17 {
 18     memset(head,-1,sizeof(head));
 19     cnt=0;
 20 }
 21 void add(int u,int v)
 22 {
 23     e[cnt].u=u;
 24     e[cnt].v=v;
 25     e[cnt].nex=head[u];
 26     head[u]=cnt++;
 27 }
 28 int pre[maxv],bccno[maxv],dfsk,bcc_cnt;
 29 stack <int> s;  //存的是邊的標號
 30 vector<int> bcc[maxv];  //存的是邊的標號
 31 int vis[maxv];
 32 
 33 int dfs(int u,int id){
 34     int lowu=pre[u]=++dfsk;
 35     for(int i=head[u];i!=-1;i=e[i].nex){
 36         int v=e[i].v;
 37         if(i==(id^1)) continue;
 38         if(!pre[v]){
 39             s.push(i);
 40             int lowv=dfs(v,i);
 41             lowu=min(lowu,lowv);
 42             if(lowv>pre[u]) ans1++;  //割邊
 43             if(lowv>=pre[u]){
 44                 bcc_cnt++;
 45                 bcc[bcc_cnt].clear();
 46                 for(;;){
 47                     int p=s.top();
 48                     s.pop();
 49                     bcc[bcc_cnt].push_back(p);
 50                     if(p==i) break;
 51                 }
 52             }
 53         }
 54         else if(pre[v]<pre[u]){
 55             s.push(i);
 56             lowu=min(lowu,pre[v]);
 57         }
 58     }
 59     return lowu;
 60 }
 61 
 62 void find_bcc(int n){
 63     memset(pre,0,sizeof(pre));
 64     memset(bccno,0,sizeof(bccno));
 65     dfsk=bcc_cnt=0;
 66     for(int i=0;i<n;i++) if(!pre[i]) dfs(i,-1);
 67 }
 68 
 69 int main(){
 70        while(scanf("%d%d",&n,&m)&&(n||m)){
 71            init();
 72            ans1=ans2=0;
 73            int u,v;
 74            for(int i=0;i<m;i++){
 75                scanf("%d%d",&u,&v);
 76                add(u,v);
 77                add(v,u);
 78            }
 79            find_bcc(n);
 80 
 81            for(int i=1;i<=bcc_cnt;i++){
 82                 int temp=0;
 83                 memset(vis,0,sizeof(vis));
 84                 for(int j=0;j<bcc[i].size();j++){
 85                     Edge p=e[bcc[i][j]];
 86                     if(!vis[p.u]) {vis[p.u]=1;temp++;}
 87                     if(!vis[p.v]) {vis[p.v]=1;temp++;}
 88                 }
 89                 if(temp<bcc[i].size()) ans2+=bcc[i].size();
 90            }
 91            printf("%d %d\n",ans1,ans2);
 92         /*
 93         //輸出邊的順序看一下挺好的,深入了解前向星工作方式
 94            for(int i=1;i<=bcc_cnt;i++)
 95             {
 96                 for(int j=0;j<bcc[i].size();j++)
 97                     cout<<bcc[i][j]<<" ";
 98                 cout<<endl;
 99             }  
100                 
101         */ 
102        }
103 }
點雙連通

Railway HDU - 3394 (點雙連通)