tarjan裸题
先用tarjan缩点
然后找出每个连通块的入度和出度
入度为0的连通块就是taskA需要的和别的连通块连接的数量
入度和出度为0的连通块中最大值就是需要taskB的添加ans条边可以让全图都是一个强连通块
如果原先就是强联通块,则特判
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define inf 0x3f3f3f3f 5 6 using namespace std; 7 8 const int maxn = 200005; 9 const int maxm = 1000005; 10 int n, m, tol, top, cnt; 11 int maxdeep, pos; 12 int bridge; 13 int stacksize; 14 15 struct Node { 16 int v; 17 int next; 18 bool vis; 19 }; 20 21 Node edge[4 * maxn]; 22 Node node[2 * maxm]; 23 bool vis[maxn]; 24 int dfn[maxn]; 25 int low[maxn]; 26 int point[maxn]; 27 int stack[maxn]; 28 int head[maxn]; 29 int head2[maxn]; 30 31 void init() { 32 tol = cnt = top = stacksize = 0; 33 bridge = 0; 34 memset(dfn, 0, sizeof(dfn)); 35 memset(low, 0, sizeof(low)); 36 memset(head, -1, sizeof(head)); 37 memset(vis, false, sizeof(vis)); 38 memset(point, 0, sizeof(point)); 39 } 40 41 void addnode(int u, int v) { 42 node[tol].v = v; 43 node[tol].vis = false; 44 node[tol].next = head[u]; 45 head[u] = tol++; 46 } 47 48 void addedge(int u, int v) { 49 edge[tol].v = v; 50 edge[tol].next = head[u]; 51 head[u] = tol++; 52 } 53 54 void dfs(int u) { 55 int v; 56 low[u] = dfn[u] = ++cnt; 57 vis[u] = true; 58 stack[stacksize++] = u; 59 for(int i=head[u]; i!=-1; i=node[i].next) { 60 v=node[i].v; 61 if(node[i].vis) 62 continue; 63 node[i].vis = node[i^1].vis = true; 64 if(!dfn[v]) { 65 dfs(v); 66 low[u] = min(low[u],low[v]); 67 if(dfn[u] < low[v]) 68 bridge++; 69 } else if(vis[v]) { 70 low[u] = min(low[u], dfn[v]); 71 } 72 } 73 if(dfn[u] == low[u]) { 74 top++; 75 int v; 76 do { 77 v = stack[--stacksize]; 78 vis[v] = false; 79 point[v] = top; 80 } while(v != u); 81 } 82 } 83 84 void tarjan() { 85 for(int u=1; u<=n; u++) { 86 if(!dfn[u]) { 87 dfs(u); 88 } 89 } 90 } 91 92 void dfs2(int u, int deep) { 93 vis[u] = true; 94 if(deep > maxdeep) { 95 maxdeep = deep; 96 pos = u; 97 } 98 for(int i=head[u]; i!=-1; i=edge[i].next) { 99 int v = edge[i].v; 100 if(!vis[v]) { 101 dfs2(v, deep+1); 102 } 103 } 104 } 105 106 int main() { 107 while(scanf("%d%d",&n, &m) != EOF) { 108 if(n==0 && m==0) 109 break; 110 init(); 111 for(int i=1; i<=m; i++) { 112 int u, v; 113 scanf("%d%d", &u, &v); 114 if(u == v) 115 continue; 116 addnode(u, v); 117 addnode(v, u); 118 } 119 tarjan(); 120 memcpy(head2, head, sizeof(head)); 121 memset(head, -1, sizeof(head)); 122 tol = 0; 123 for(int u=1; u<=n; u++) { 124 for(int i=head2[u]; i!=-1; i=node[i].next) { 125 int v = node[i].v; 126 if(point[u] != point[v]) { 127 addedge(point[u], point[v]); 128 addedge(point[v], point[u]); 129 } 130 } 131 } 132 // for(int i=0; i<tol; i++) 133 // printf("%d %d\n",head[i]); 134 maxdeep = pos = 0; 135 memset(vis, false, sizeof(vis)); 136 vis[1] = true; 137 dfs2(1, 0); 138 memset(vis, false, sizeof(vis)); 139 maxdeep = 0; 140 vis[pos] = true; 141 dfs2(pos, 0); 142 int ans = bridge - maxdeep; 143 printf("%d\n", ans); 144 } 145 return 0; 146 }