codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点
J. Computer Network
Time Limit: 1 Sec
Memory Limit: 256 MB
题目连接
http://codeforces.com/gym/100114Description
The computer network of “Plunder & Flee Inc.” consists of n servers and m two-way communication links. Two servers can communicate either through a direct link, or through a chain of links, by relaying information from server to server. Current network setup enables communication for any pair of servers. The network administrator strives to maximize network reliability. Some communication links in the network were identified as critical. A failure on any critical link will split the network into disconnected segments. Company management responded to the administrator’s concerns and agreed to fund another communication link, provided that when the new link goes online the number of critical links will be minimized. Write a program that, given a network configuration, will pick a pair of servers to be connected by the new communication link. If several such pairs allow minimizing the number of critical links then any of them will be considered as a correct answer. Example. The following figure presents a network consisting of 7 servers and 7 communication links. Essential links are shown as bold lines. A new link connecting servers #1 and #7 (dotted line) can reduce the number of the critical links to only one
Input
Output
Sample Input
7 7 1 2 2 3 2 4 2 6 3 4 4 5 6 7
Sample Output
HINT
题意
给你一个图,让你连一条边之后,使得这个图的桥最少
题解:
缩点变成一颗树之后,跑树的直径,然后把树的直径的两端连起来就行了
代码:
1 #pragma comment(linker, "/STACK:102400000,102400000") 2 #include<iostream> 3 #include<stdio.h> 4 #include<string.h> 5 const int VM = 200005; 6 const int EM = 1000005; 7 8 struct Edeg 9 { 10 int to,nxt,vis; 11 }edge[EM<<1],tree[EM<<1]; 12 13 int head[VM],vis[VM],thead[VM]; 14 int dfn[VM],low[VM],stack[VM],belong[VM]; 15 int ep,bridge,son,maxn,src,n,cnt,scc,top; 16 int te[VM]; 17 int max (int a,int b) 18 { 19 return a > b ? a : b; 20 } 21 int min(int a ,int b) 22 { 23 return a > b ? b : a; 24 } 25 void addedge (int cu,int cv) 26 { 27 edge[ep].to = cv; 28 edge[ep].vis = 0; 29 edge[ep].nxt = head[cu]; 30 head[cu] = ep ++; 31 edge[ep].to = cu; 32 edge[ep].vis = 0; 33 edge[ep].nxt = head[cv]; 34 head[cv] = ep ++; 35 } 36 void Buildtree(int cu,int cv) 37 { 38 tree[son].to = cv; 39 tree[son].nxt = thead[cu]; 40 thead[cu] = son ++; 41 } 42 void Tarjan (int u) 43 { 44 int v; 45 vis[u] = 1; 46 dfn[u] = low[u] = ++cnt; 47 stack[top++] = u; 48 for (int i = head[u];i != -1;i = edge[i].nxt) 49 { 50 v = edge[i].to; 51 if (edge[i].vis) continue; // 52 edge[i].vis = edge[i^1].vis = 1; //正向边访问过了,反向边得标志,否则两点会成一块。 53 if (vis[v] == 1) 54 low[u] = min(low[u],dfn[v]); 55 if (!vis[v]) 56 { 57 Tarjan (v); 58 low[u] = min(low[u],low[v]); 59 if (low[v] > dfn[u]) 60 bridge ++; 61 } 62 } 63 if (dfn[u] == low[u]) 64 { 65 ++scc; 66 do{ 67 v = stack[--top]; 68 vis[v] = 0; 69 belong[v] = scc; 70 te[scc]=v; 71 }while (u != v); 72 } 73 } 74 void BFS(int u) 75 { 76 int que[VM+100]; 77 int front ,rear,i,v; 78 front = rear = 0; 79 memset (vis,0,sizeof(vis)); 80 que[rear++] = u; 81 vis[u] = 1; 82 while (front != rear) 83 { 84 u = que[front ++]; 85 front = front % (n+1); 86 for (i = thead[u];i != -1;i = tree[i].nxt) 87 { 88 v = tree[i].to; 89 if (vis[v]) continue; 90 vis[v] = 1; 91 que[rear++] = v; 92 rear = rear%(n+1); 93 } 94 } 95 src = que[--rear];//求出其中一个端点 96 } 97 int ans2=0; 98 void DFS (int u,int dep) 99 { 100 if(maxn<dep) 101 { 102 maxn = max(maxn,dep); 103 ans2 = u; 104 } 105 vis[u] = 1; 106 for (int i = thead[u]; i != -1; i = tree[i].nxt) 107 { 108 int v = tree[i].to; 109 if (!vis[v]) 110 DFS (v,dep+1); 111 } 112 } 113 void solve() 114 { 115 int u,v; 116 memset (vis,0,sizeof(vis)); 117 cnt = bridge = scc = top = 0; 118 Tarjan (1); 119 memset (thead,-1,sizeof(thead)); 120 son = 0; 121 for (u = 1;u <= n;u ++) //重构图 122 for (int i = head[u];i != -1;i = edge[i].nxt) 123 { 124 v = edge[i].to; 125 if (belong[u]!=belong[v]) 126 { 127 Buildtree (belong[u],belong[v]); 128 Buildtree (belong[v],belong[u]); 129 } 130 } 131 maxn = 0; //最长直径 132 BFS(1); //求树直径的一个端点 133 memset (vis,0,sizeof(vis)); 134 DFS(src,0); //求树的最长直径 135 printf("%d %d\n",te[src],te[ans2]); 136 //printf ("%d\n",bridge-maxn); 137 } 138 139 int main () 140 { 141 freopen("input.txt","r",stdin); 142 freopen("output.txt","w",stdout); 143 int m,u,v; 144 while (~scanf ("%d%d",&n,&m)) 145 { 146 if (n == 0&&m == 0) 147 break; 148 memset (head,-1,sizeof(head)); 149 ep = 0; 150 while (m --) 151 { 152 scanf ("%d%d",&u,&v); 153 addedge (u,v); 154 } 155 solve(); 156 } 157 return 0; 158 }