Railway HDU - 3394 (点双连通)

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 }
点双连通

 

转载于:https://www.cnblogs.com/yijiull/p/7390406.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值