Hdu 4612 Warm up (双连通分支+树的直径)
题目链接:
题目描述:
给一个无向连通图,问加上一条边后,桥的数目最少会有几个?
解题思路:
题目描述很清楚,题目也很裸,就是一眼看穿怎么做的,先求出来双连通分量,然后缩点重新建图,用bfs求树的直径,直径的长度就是减去桥的数目。
这个题目需要手动扩展,而且手动扩展的话要用C++提交,G++re哭了。
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #pragma comment(linker, "/STACK:1024000000,1024000000") 7 using namespace std; 8 9 const int maxn = 200005; 10 struct node 11 { 12 int to, next; 13 }edge[10*maxn], Edge[2*maxn]; 14 int vis[maxn], dist[maxn]; 15 int head[maxn], low[maxn], dfn[maxn], id[maxn], Head[maxn]; 16 int stack[maxn], tot, Tot, ntime, top, cnt, Max, end_p; 17 18 void init () 19 { 20 tot = ntime = top = Tot = cnt = Max = end_p = 0; 21 memset (id, 0, sizeof(id)); 22 memset (low, 0, sizeof(low)); 23 memset (dfn, 0, sizeof(dfn)); 24 memset (head, -1, sizeof(head)); 25 memset (stack, 0, sizeof(stack)); 26 memset (Head, -1, sizeof(Head)); 27 } 28 void Add (int from, int to) 29 { 30 Edge[Tot].to = to; 31 Edge[Tot].next = Head[from]; 32 Head[from] = Tot ++; 33 } 34 void add (int from, int to) 35 { 36 edge[tot].to = to; 37 edge[tot].next = head[from]; 38 head[from] = tot ++; 39 } 40 void Tarjan (int u, int father) 41 { 42 int k = 0; 43 low[u] = dfn[u] = ++ntime; 44 stack[top++] = u; 45 for (int i=head[u]; i!=-1; i=edge[i].next) 46 { 47 int v = edge[i].to; 48 if (v == father && !k) 49 { 50 k ++; 51 continue; 52 } 53 if (!dfn[v]) 54 { 55 Tarjan (v, u); 56 low[u] = min (low[u], low[v]); 57 } 58 else 59 low[u] = min (low[u], dfn[v]); 60 } 61 if (low[u] == dfn[u]) 62 { 63 cnt ++; 64 while (1) 65 { 66 int v = stack[--top]; 67 id[v] = cnt; 68 if (v == u) 69 break; 70 } 71 } 72 } 73 void bfs (int s) 74 { 75 queue<int>Q; 76 int u, v; 77 memset (vis, 0,sizeof(vis)); 78 vis[s] = 1; 79 dist[s] = 0; 80 Q.push(s); 81 while (!Q.empty()) 82 { 83 u = Q.front(); 84 Q.pop(); 85 for (int i=Head[u]; i!=-1; i=Edge[i].next) 86 { 87 v = Edge[i].to; 88 if (!vis[v]) 89 { 90 vis[v] = 1; 91 dist[v] = dist[u] + 1; 92 Q.push(v); 93 if (dist[v] > Max) 94 { 95 Max = dist[v]; 96 end_p = v; 97 } 98 } 99 } 100 } 101 } 102 void solve (int n) 103 { 104 int sum = 0; 105 Tarjan (1, 0); 106 for (int i=1; i<=n; i++) 107 for (int j=head[i]; j!=-1; j=edge[j].next) 108 { 109 int u = id[i]; 110 int v = id[edge[j].to]; 111 if (v != u) 112 { 113 Add (u, v); 114 sum ++; 115 } 116 } 117 sum /= 2; 118 bfs (1); 119 bfs (end_p); 120 printf ("%d\n", sum - Max); 121 } 122 int main () 123 { 124 int n, m; 125 while (scanf ("%d %d", &n, &m), n+m) 126 { 127 init (); 128 while (m --) 129 { 130 int u, v; 131 scanf ("%d %d", &u, &v); 132 add (u, v); 133 add (v, u); 134 } 135 solve (n); 136 } 137 return 0; 138 }
本文为博主原创文章,未经博主允许不得转载。