无向图求割边缩点,边连通图
题意:给你一个无向连通图,问加上一条边后得到的图的最少的割边数。
先求无向图的割边,然后把边连通图缩点,得到的所有缩点连成一棵树,最后就是求树上的最长路。
#pragma comment(linker,"/STACK:100000000,100000000") #include <stdio.h> #include <string.h> #include <vector> #define pb push_back using namespace std; const int maxn = 200002; const int maxm = 1000002; struct EDGE{ int next, to, vis; }edge[maxm*2]; struct GEEDGE { int u, to; }geedge[maxm]; int head[maxn], dfn[maxn], E, time, top, low[maxn], st[maxn], belo[maxn], type, getot; int min(int a, int b) { return a > b ? b : a; } int max(int a, int b) { return a > b ? a : b; } void init() { memset(head, -1, sizeof(head)); memset(dfn, 0, sizeof(dfn)); memset(belo, 0, sizeof(belo)); E = top = time = type = getot = 0; } void newedge(int u, int to) { edge[E].to = to; edge[E].next = head[u]; edge[E].vis = 0; head[u] = E++; } void dfs(int u) { low[u] = dfn[u] = ++time; st[++top] = u; for(int i = head[u];i != -1;i = edge[i].next) { if(edge[i].vis) continue; edge[i].vis = edge[i^1].vis = 1; int to = edge[i].to; if(!dfn[to]) { dfs(to); low[u] = min(low[u], low[to]); if(low[to] > dfn[u]) { type++; int v; do { v = st[top--]; belo[v] = type; } while(v != to); geedge[getot].u = u; geedge[getot++].to = to; } } else low[u] = min(low[u], low[to]); } } int ans; int DFS(int u) { int mx = 0, tmx = 0; for(int i = head[u];i != -1;i = edge[i].next) { if(edge[i].vis) continue; edge[i].vis = edge[i^1].vis = 1; int to = edge[i].to; int now = DFS(to)+1; if(now >= mx) { tmx = mx; mx = now; } else if(now > tmx) tmx = now; } ans = max(ans, tmx+mx); return mx; } int main() { int n, m, i, u, to, j; while(scanf("%d%d", &n, &m) != -1 && n) { init(); for(i = 0;i < m; i++) { scanf("%d%d", &u, &to); newedge(u, to); newedge(to, u); } for(i = 1;i <= n; i++) if(!dfn[i]) dfs(i); E = 0; memset(head, -1, sizeof(head)); for(i = 0;i < getot; i++) { u = geedge[i].u; to = geedge[i].to; newedge(belo[u], belo[to]); newedge(belo[to], belo[u]); } ans = 0; DFS(0); printf("%d\n", getot - ans); } return 0; }