【HDOJ】4612 Warm up
双连通缩点+求树的直径,图论基础题目。
1 /* 4612 */ 2 #pragma comment(linker, "/STACK:1024000000,1024000000") 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <cstdio> 8 #include <cstring> 9 #include <cstdlib> 10 using namespace std; 11 12 #define MAXV 200005 13 #define MAXE 1000005 14 15 typedef struct { 16 int v, next; 17 } Edge_t; 18 19 Edge_t E[MAXE*2]; 20 vector<int> vc[MAXV]; 21 int low[MAXV], pre[MAXV]; 22 int bn[MAXV]; 23 int S[MAXV], top; 24 int head[MAXV], L; 25 bool visit[MAXV]; 26 int dfs_clock, block; 27 int n, m; 28 29 void addEdge(int u, int v) { 30 E[L].v = v; 31 E[L].next = head[u]; 32 head[u] = L++; 33 } 34 35 void init() { 36 memset(head, -1, sizeof(int)*(n+1)); 37 memset(pre, 0, sizeof(int)*(n+1)); 38 memset(bn, 0, sizeof(int)*(n+1)); 39 dfs_clock = block = L = top = 0; 40 } 41 42 void tarjan(int u, int fa) { 43 int i, j, k, v; 44 45 S[top++] = u; 46 pre[u] = low[u] = ++dfs_clock; 47 for (i=head[u]; i!=-1; i=E[i].next) { 48 if (i == (fa^1)) 49 continue; 50 v = E[i].v; 51 if (!pre[v]) { 52 tarjan(v, i); 53 low[u] = min(low[u], low[v]); 54 } else if (!bn[v]) { 55 low[u] = min(low[u], pre[v]); 56 } 57 } 58 if (low[u] == pre[u]) { 59 ++block; 60 do { 61 bn[S[--top]] = block; 62 } while (S[top]!=u); 63 } 64 } 65 66 void solve() { 67 queue<int> Q; 68 int i, j, k; 69 int u = 1, v; 70 71 memset(pre, 0, sizeof(int)*(block+1)); 72 pre[u] = 1; 73 Q.push(u); 74 while (!Q.empty()) { 75 u = Q.front(); 76 Q.pop(); 77 for (i=0; i<vc[u].size(); ++i) { 78 v = vc[u][i]; 79 if (!pre[v]) { 80 pre[v] = 1; 81 Q.push(v); 82 } 83 } 84 } 85 86 memset(pre, 0, sizeof(int)*(block+1)); 87 pre[u] = 1; 88 Q.push(u); 89 while (!Q.empty()) { 90 u = Q.front(); 91 Q.pop(); 92 k = pre[u]; 93 for (i=0; i<vc[u].size(); ++i) { 94 v = vc[u][i]; 95 if (!pre[v]) { 96 pre[v] = k+1; 97 Q.push(v); 98 } 99 } 100 } 101 102 printf("%d\n", block-pre[u]); 103 } 104 105 int main() { 106 int i, j, k; 107 108 #ifndef ONLINE_JUDGE 109 freopen("data.in", "r", stdin); 110 freopen("data.out", "w", stdout); 111 #endif 112 113 while (scanf("%d %d",&n,&m)!=EOF && (n||m)) { 114 init(); 115 for (i=0; i<m; ++i) { 116 scanf("%d %d", &j, &k); 117 addEdge(j, k); 118 addEdge(k, j); 119 } 120 for (i=1; i<=n; ++i) 121 if (!pre[i]) 122 tarjan(i, -1); 123 for (i=1; i<=block; ++i) 124 vc[i].clear(); 125 for (i=1; i<=n; ++i) { 126 for (j=head[i]; j!=-1; j=E[j].next) { 127 k = E[j].v; 128 if (bn[i] != bn[k]) { 129 // bridge 130 vc[bn[i]].push_back(bn[k]); 131 vc[bn[k]].push_back(bn[i]); 132 } 133 } 134 } 135 solve(); 136 } 137 138 return 0; 139 }