题目:给出一个图,添加一条边之后,问能够在新图中得到的最少的桥的数量。
分析:我们可以双联通分量进行缩点,原图变成了一棵树。问题变成了:求树中添加一条边之后,使得不在圈的边最少。显然求一边直径,用总边数减掉最长路上的边数就是答案。注意数据存在重边的情况。
#include <set> #include <map> #include <list> #include <cmath> #include <queue> #include <stack> #include <string> #include <vector> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; #define debug puts("here") #define rep(i,n) for(int i=0;i<n;i++) #define rep1(i,n) for(int i=1;i<=n;i++) #define REP(i,a,b) for(int i=a;i<=b;i++) #define foreach(i,vec) for(unsigned i=0;i<vec.size();i++) #define pb push_back #define RD(n) scanf("%d",&n) #define RD2(x,y) scanf("%d%d",&x,&y) #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z) #define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w) #define All(vec) vec.begin(),vec.end() #define MP make_pair #define PII pair<int,int> #define PQ priority_queue #define cmax(x,y) x = max(x,y) #define cmin(x,y) x = min(x,y) #define Clear(x) memset(x,0,sizeof(x)) /* #pragma comment(linker, "/STACK:1024000000,1024000000") int size = 256 << 20; // 256MB char *p = (char*)malloc(size) + size; __asm__("movl %0, %%esp " :: "r"(p) ); */ char IN; bool NEG; inline void Int(int &x){ NEG = 0; while(!isdigit(IN=getchar())) if(IN=='-')NEG = 1; x = IN-'0'; while(isdigit(IN=getchar())) x = x*10+IN-'0'; if(NEG)x = -x; } inline void LL(ll &x){ NEG = 0; while(!isdigit(IN=getchar())) if(IN=='-')NEG = 1; x = IN-'0'; while(isdigit(IN=getchar())) x = x*10+IN-'0'; if(NEG)x = -x; } /******** program ********************/ const int MAXN = 200005; const int MAXM = 1000005; vector<int> adj[MAXN]; int po[MAXN],tol; int low[MAXN],dfn[MAXN],tim; bool use[MAXN]; int fa[MAXN]; int id[MAXN],ha[MAXN]; struct Edge{ int y,id,next; }edge[MAXM<<1]; inline void add(int x,int y,int i){ edge[++tol].y = y; edge[tol].id = i; edge[tol].next = po[x]; po[x] = tol; } int findSet(int x){ if(x!=fa[x]) fa[x] = findSet(fa[x]); return fa[x]; } void dfs(int x,int fid){ low[x] = dfn[x] = ++ tim; for(int i=po[x];i;i=edge[i].next){ int y = edge[i].y; int id = edge[i].id; if(id==fid)continue; if(!dfn[y]){ dfs(y,id); cmin( low[x],low[y] ); if(low[y]<=dfn[x]){ int px = findSet(x); int py = findSet(y); if(px!=py)fa[px] = py; } }else cmin( low[x],dfn[y] ); } } int MAX,root; void dfsR(int x,int sz){ use[x] = true; if(sz>MAX){ MAX = sz; root = x; } foreach(i,adj[x]) if(!use[adj[x][i]]) dfsR(adj[x][i],sz+1); } int main(){ #ifndef ONLINE_JUDGE freopen("1002.in","r",stdin); //freopen("sum.out","w",stdout); #endif int size = 256 << 20; // 256MB char *p = (char*)malloc(size) + size; __asm__("movl %0, %%esp " :: "r"(p) ); int x,y,n,m; while(1){ Int(n);Int(m); if(!n&&!m)break; Clear(po); tol = 0; rep1(i,m){ Int(x);Int(y); add(x,y,i); add(y,x,i); } rep1(i,n){ adj[i].clear(); fa[i] = i; } Clear(dfn); tim = 0; rep1(i,n) if(!dfn[i]) dfs(i,0); Clear(id); int tot = 0; rep1(i,n){ int px = findSet(i); if(!id[px])id[px] = ++tot; ha[i] = id[px]; } rep1(x,n){ int px = ha[x]; for(int i=po[x];i;i=edge[i].next){ int py = ha[ edge[i].y ]; if(px==py)continue; adj[px].pb(py); adj[py].pb(px); } } Clear(use); MAX = 0; dfsR(1,1); Clear(use); MAX = 0; dfsR(root,1); printf("%d ",tot-MAX); } return 0; }