zoukankan      html  css  js  c++  java
  • POJ 3352 Road Construction(边—双连通分量)

    http://poj.org/problem?id=3352

    题意:

    给出一个图,求最少要加多少条边,能把该图变成边—双连通。

    思路:
    双连通分量是没有桥的,dfs一遍,计算出每个结点的low值,如果相等,说明属于同一个双连通分量。

    接下来把连通分量缩点,然后把这些点连边。

    对于一棵无向树,我们要使得其变成边双连通图,需要添加的边数 == (树中度数为1的点的个数+1)/2。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 using namespace std;
     11 
     12 const int maxn=50000+5;
     13 
     14 int n,m;
     15 int pre[maxn],isbridge[maxn],bccno[maxn],bcc_cnt,dfs_clock;
     16 int low[maxn];   //low[i]表示i结点及其后代能通过反向边连回的最早的祖先的pre值
     17 int degree[maxn];
     18 vector<int> G[maxn],bcc[maxn];
     19 
     20 int tarjan(int u,int fa)
     21 {
     22     int lowu=pre[u]=++dfs_clock;
     23     for(int i=0;i<G[u].size();i++)
     24     {
     25         int v=G[u][i];
     26         if(!pre[v])
     27         {
     28             int lowv=tarjan(v,u);
     29             lowu=min(lowu,lowv);
     30             /*
     31             if(lowv>pre[u])
     32                 isbridge[G[u][i]]=isbridge[G[u][i]^1]=1;    //桥
     33                 */
     34         }
     35         else if(pre[v]<pre[u] && v!=fa)
     36             lowu=min(lowu,pre[v]);
     37     }
     38     return low[u]=lowu;
     39 }
     40 
     41 /*
     42 void dfs(int u)
     43 {
     44     pre[u]=1;
     45     bccno[u]=bcc_cnt;
     46     for(int i=0;i<G[u].size();i++)
     47     {
     48         int v=G[u][i];
     49         if(isbridge[v])   continue;
     50         if(!pre[v])  dfs(v);
     51     }
     52 }
     53 */
     54 
     55 /*
     56 void find_ebbc()
     57 {
     58     bcc_cnt=dfs_clock=0;
     59     memset(pre,0,sizeof(pre));
     60     memset(isbridge,0,sizeof(isbridge));
     61     memset(bcc,0,sizeof(bcc));
     62     memset(bccno,0,sizeof(bccno));
     63     for(int i=1;i<=n;i++)
     64         if(!pre[i])   tarjan(i,-1);
     65 
     66     memset(pre,0,sizeof(pre));
     67     for(int i=1;i<=n;i++)             //计算边—双连通分量
     68         if(!pre[i])
     69         {
     70             bcc_cnt++;
     71             dfs(i);
     72         }
     73 }
     74 */
     75 
     76 int main()
     77 {
     78     //freopen("D:\input.txt","r",stdin);
     79     while(~scanf("%d%d",&n,&m) && n && m)
     80     {
     81         for(int i=1;i<=n;i++)  G[i].clear();
     82         for(int i=0;i<m;i++)
     83         {
     84             int u,v;
     85             scanf("%d%d",&u,&v);
     86             G[u].push_back(v);
     87             G[v].push_back(u);
     88         }
     89         //find_ebbc();
     90         tarjan(1,-1);
     91         for(int i=1;i<=n;i++)
     92         {
     93             for(int j=0;j<G[i].size();j++)
     94             {
     95                 int v=G[i][j];
     96                 if(low[i]!=low[v])
     97                     degree[low[v]]++;
     98             }
     99         }
    100         int cnt=0;
    101         for(int i=1;i<=n;i++)
    102             if(degree[i]==1)  cnt++;
    103         printf("%d
    ",(cnt+1)/2);
    104     }
    105     return 0;
    106 }
  • 相关阅读:
    我的数学之美(一)——RANSAC算法详解
    机器学习经典算法之-----最小二乘法(zz)
    基于大数据的餐饮推荐系统总结
    Hive 数据错位修复方案
    Python 2.x 判断 Excel 是否包含指定的 sheet
    Shell脚本判断目录是否为空
    MySQL启动报错 The server quit without updating PID file 解决方案
    DolphinScheduler 1.3.2集群版(基于CDH5.13.1)安装手册
    添加 Shell 脚本的启动用户限制
    CentOS 7 离线安装 MySQL 5.7
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/6781311.html
Copyright © 2011-2022 走看看