zoukankan      html  css  js  c++  java
  • POJ 3177 Redundant Paths(强连通分量)

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

    题目大意是一个无向图给你n个点m条边,让你求出最少加多少条边 可以让任意两个点相通两条及以上的路线(每条路线点可以重复,但是每条路径上不能有重边),简单来说就是让你加最少的边使这个图变成一个双连通图。

    首先用tarjan来缩点,可以得到一个新的无环图,要是只有一个强连通分量,那本身就是一个双连通图。要是多个强连通分量,那我们可以考虑缩点后度数为1的点(肯定是由这个点开始连新边最优),那我们假设数出度数为1的点的个数为cnt,可以画几个图观察可得答案就是(cnt + 1) / 2。但是这题有个问题就是要去掉重边(A B和B A不算重边),不然会wa...,所以我用了二维map来去重边。

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <vector>
     5 #include <map>
     6 using namespace std;
     7 const int MAXN = 5005;
     8 map <int , map<int , int> > mp;
     9 struct data {
    10     int next , to;
    11 }edge[MAXN * 5];
    12 int head[MAXN] , low[MAXN] , dfn[MAXN] , st[MAXN] , block[MAXN] , du[MAXN];
    13 int top , ord , sccnum , cont;
    14 bool instack[MAXN];
    15 
    16 void init() {
    17     memset(head , -1 , sizeof(head));
    18     memset(instack , false , sizeof(instack));
    19     memset(low , 0 , sizeof(low));
    20     memset(dfn , 0 , sizeof(dfn));
    21     memset(du , 0 , sizeof(du));
    22     top = ord = sccnum = cont = 0;
    23 }
    24 
    25 void add(int u , int v) {
    26     edge[cont].next = head[u];
    27     edge[cont].to = v;
    28     head[u] = cont++;
    29 }
    30 
    31 void tarjan(int u , int par) {
    32     low[u] = dfn[u] = ++ord;
    33     st[++top] = u;
    34     instack[u] = true;
    35     for(int i = head[u] ; ~i ; i = edge[i].next) {
    36         int v = edge[i].to;
    37         if(v == par)
    38             continue;
    39         if(!dfn[v]) {
    40             tarjan(v , u);
    41             low[u] = min(low[u] , low[v]);
    42         }
    43         else if(instack[v]) {
    44             low[u] = min(low[u] , dfn[v]);
    45         }
    46     }
    47     if(low[u] == dfn[u]) {
    48         int v;
    49         sccnum++;
    50         do {
    51             v = st[top--];
    52             instack[v] = false;
    53             block[v] = sccnum;
    54         }while(u != v);
    55     }
    56 }
    57 
    58 int main()
    59 {
    60     int n , m , u , v;
    61     while(~scanf("%d %d" , &n , &m)) {
    62         init();
    63         mp.clear();
    64         while(m--) {
    65             scanf("%d %d" , &u , &v);
    66             if(!mp[u][v]) {
    67                 add(u , v);
    68                 add(v , u);
    69                 mp[u][v]++;
    70             }
    71         }
    72         tarjan(1 , -1);
    73         for(int u = 1 ; u <= n ; u++) {
    74             for(int i = head[u] ; ~i ; i = edge[i].next) {
    75                 int v = edge[i].to;
    76                 if(block[u] != block[v]) {
    77                     du[block[u]]++;
    78                 }
    79             }
    80         }
    81         int res = 0;
    82         for(int i = 1 ; i <= sccnum ; i++) {
    83             if(du[i] == 1)
    84                 res++;
    85         }
    86         printf("%d
    " , (res + 1) / 2);
    87     }
    88 }
  • 相关阅读:
    zabbix迁移思路
    top命令
    random随机数
    判断传入元素是否可见
    title_contains
    1.Selenium的工作原理以及网页上查找元素
    APP升级测试
    英语词汇
    作文 |素材笔记
    408计组 |二、数据的表示和运算
  • 原文地址:https://www.cnblogs.com/Recoder/p/5263534.html
Copyright © 2011-2022 走看看