• poj 3352(边双连通分量)


    题目链接:http://poj.org/problem?id=3352

    思路:可以求出所有的桥,把桥删掉。然后把所有的连通分支求出来,显然这些连通分支就是原图中的双连通分支。把它们缩成点,然后添上刚才删去的桥,就构成了一棵树。在树上添边使得树变成一个双连通分支即可,这里我们可以直接统计缩点后的叶子节点个数即可,从而要加的边数即为(叶子节点个数+1)/2.

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<stack>
     6 #include<queue>
     7 #include<vector>
     8 using namespace std;
     9 #define MAXN 2222
    10 
    11 stack<int>S;
    12 vector<int>map[MAXN];
    13 
    14 int low[MAXN],dfn[MAXN];
    15 int color[MAXN];
    16 bool mark[MAXN];
    17 int degree[MAXN];
    18 int n,m,cnt,_count;
    19 
    20 void Tarjan(int u,int father)
    21 {
    22     low[u]=dfn[u]=++cnt;
    23     mark[u]=true;
    24     S.push(u);
    25     for(int i=0;i<map[u].size();i++){
    26         int v=map[u][i];
    27         if(v==father)continue;
    28         if(dfn[v]==0){
    29             Tarjan(v,u);
    30             low[u]=min(low[u],low[v]);
    31         }else if(mark[v]){
    32             low[u]=min(low[u],dfn[v]);
    33         }
    34     }
    35     if(low[u]==dfn[u]){
    36         int v;
    37         _count++;
    38         do{
    39             v=S.top();
    40             S.pop();
    41             mark[v]=false;
    42             color[v]=_count;
    43         }while(u!=v);
    44     }
    45 }
    46 
    47 int main()
    48 {
    49     int u,v;
    50     while(~scanf("%d%d",&n,&m)){
    51         for(int i=1;i<=n;i++)map[i].clear();
    52         memset(low,0,sizeof(low));
    53         memset(dfn,0,sizeof(dfn));
    54         memset(mark,false,sizeof(mark));
    55         memset(degree,0,sizeof(degree));
    56         memset(color,0,sizeof(color));
    57         cnt=_count=0;
    58         while(m--){
    59             scanf("%d%d",&u,&v);
    60             map[u].push_back(v);
    61             map[v].push_back(u);
    62         }
    63         for(int i=1;i<=n;i++){
    64             if(dfn[i]==0)Tarjan(i,-1);
    65         }
    66         for(int i=1;i<=n;i++){
    67             for(int j=0;j<map[i].size();j++){
    68                 if(color[i]!=color[map[i][j]]){
    69                     degree[color[i]]++;
    70                 }
    71             }
    72         }
    73         cnt=0;
    74         for(int i=1;i<=_count;i++){
    75             if(degree[i]==1)cnt++;
    76         }
    77         printf("%d
    ",(cnt+1)/2);
    78     }
    79     return 0;
    80 }
    81             
    82         
    83             
    84     
    85             
    View Code
  • 相关阅读:
    linux 运维
    mariadb replication
    phpmyadmin
    Objective-C设计模式——单例Singleton(对象创建)
    收藏iOS学习资料
    axios拦截器
    vue单页面优化
    html设置http缓存代码
    js数组去重,排序的几种方法
    前端移动端问题
  • 原文地址:https://www.cnblogs.com/wally/p/3204792.html
Copyright © 2020-2023  润新知