POJ 3177 - Redundant Paths - 双连通分量

Posted onlynagesha

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3177 - Redundant Paths - 双连通分量相关的知识,希望对你有一定的参考价值。

题目大意:

给定一个N个点,M条边的无向连通图(可能有重边),要求让任意两点间都有两条或以上的路径,且这些路径没有公共边。问至少需要加多少条边?

N<=5e3,M<=1e4。

求双连通分量并缩点。详见:https://www.cnblogs.com/frog112111/p/3367039.html

注意由于本题数据允许重边(尽管讨论区有人吐槽数据太水),DFS时判断割边的条件应为low[to] > dfn[cur],该边的重数为1。

实现的时候用了并查集来维护属于同一双联通分量的点,标记割边时将它的重数变成-1。

代码:(都8102年了贵OJ还不支持C++11-_-||)

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <map>
  5 
  6 using namespace std;
  7 
  8 const int maxN = 5000 + 5;
  9 const int notVisited = -1;
 10 
 11 map<int, int> elist[maxN];
 12 int dfn[maxN];
 13 int low[maxN];
 14 int ufs[maxN];
 15 int cnt[maxN];
 16 int lastDfn = 0;
 17 int N, M;
 18 
 19 inline void addEdge(int u, int v)
 20 {
 21     map<int, int>::iterator it = elist[u].find(v);
 22     if (it != elist[u].end())
 23         it->second += 1;
 24     else
 25         elist[u].insert(make_pair(v, 1));
 26 }
 27 
 28 void input()
 29 {
 30     scanf("%d%d", &N, &M);
 31     for (int u, v, i = 1; i <= M; i++)
 32     {
 33         scanf("%d%d", &u, &v);
 34         addEdge(u, v);
 35         addEdge(v, u);
 36     }
 37 }
 38 
 39 void init()
 40 {
 41     memset(dfn, -1, sizeof(dfn));
 42     memset(low, 0x3f, sizeof(low)); //infinity
 43     lastDfn = 0;
 44     for (int i = 1; i <= N; i++)
 45         ufs[i] = i;
 46 }
 47 
 48 int findUfs(int x)
 49 {
 50     return ufs[x] == x ? x : (ufs[x] = findUfs(ufs[x]));
 51 }
 52 
 53 bool unifyUfs(int x, int y)
 54 {
 55     int fx = findUfs(x);
 56     int fy = findUfs(y);
 57     if (fx == fy)
 58         return false;
 59     ufs[fx] = fy;
 60     return true;
 61 }
 62 
 63 void dfs(int cur, int last)
 64 {
 65     dfn[cur] = low[cur] = (++lastDfn);
 66 
 67     for (map<int, int>::iterator it = elist[cur].begin(); it != elist[cur].end(); ++it)
 68     {
 69         int to = it->first;
 70         if (dfn[to] == notVisited)
 71         {
 72             dfs(to, cur);
 73             if (it->second >= 2 || low[to] <= dfn[cur])
 74                 unifyUfs(cur, to);
 75             else
 76                 it->second = -1;
 77             low[cur] = min(low[cur], low[to]);
 78         }
 79         else if (to != last)
 80         {
 81             unifyUfs(to, cur);
 82             low[cur] = min(low[cur], dfn[to]);
 83         }
 84     }
 85 }
 86 
 87 int solve()
 88 {
 89     init();
 90     dfs(1, 0);
 91 
 92     for (int i = 1; i <= N; i++)
 93         for (map<int, int>::iterator it = elist[i].begin(); it != elist[i].end(); ++it)
 94         {
 95             if (it->second > 0)
 96                 continue;
 97 
 98             int to = it->first;
 99             int fi = findUfs(i);
100             int ft = findUfs(to);
101             if (fi != ft)
102             {
103                 cnt[fi] += 1;
104                 cnt[ft] += 1;
105             }
106         }
107 
108     return ((int)count(cnt + 1, cnt + N + 1, 1) + 1) / 2;
109 }
110 
111 int main()
112 {
113     input();
114     printf("%d", solve());
115     return 0;
116 }

 

以上是关于POJ 3177 - Redundant Paths - 双连通分量的主要内容,如果未能解决你的问题,请参考以下文章

POJ3177 Redundant Paths 双连通分量

无向图缩点poj3177 Redundant Paths

[双连通分量] POJ 3177 Redundant Paths

Redundant Paths POJ - 3177(边双连通)

poj3177:Redundant Paths——题解

POJ 3177 Redundant Paths