hdu4612:http://acm.hdu.edu.cn/showproblem.php?pid=4612
题意:给你一个无向连通图,问加上一条边后得到的图的最少的割边数;
题解:首先对原图求割边数,然后缩点之后建树,然后求树的直径。因为加上一条边,能消耗最大的割边就是树的直径。一道很好的模板题目。
1 #pragma comment(linker,"/STACK:100000000,100000000")//阔栈的语句 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #define pb push_back 6 using namespace std; 7 const int maxn = 200002; 8 const int maxm = 1000002; 9 struct EDGE{ 10 int next, to, vis; 11 }edge[maxm*2];//记录边,vis表示这一条边是否被访问 12 struct GEEDGE { 13 int u, to; 14 }geedge[maxm];//记录割边 15 int n,m,time,top,type,getot,cnt;//time是时间戳,type标记连通块,getot割边的数量,cnt边数 16 int head[maxn],st[maxn],dfn[maxn],low[maxn],belo[maxn];//belo[i],表示i属于哪个连通块 17 int start,ans1,ans,u,v; 18 void init(){ 19 time=top=type=getot=cnt=0; 20 memset(head,-1,sizeof(head)); 21 memset(dfn,0,sizeof(dfn)); 22 memset(low,0,sizeof(low)); 23 memset(belo,0,sizeof(belo)); 24 } 25 void add(int u,int v){ 26 edge[cnt].to=v; 27 edge[cnt].next=head[u]; 28 edge[cnt].vis=0; 29 head[u]=cnt++; 30 } 31 void dfs(int u) { 32 low[u] = dfn[u] = ++time; 33 st[++top] = u; 34 for(int i = head[u];i != -1;i = edge[i].next) { 35 if(edge[i].vis) continue; 36 edge[i].vis = edge[i^1].vis = 1; 37 int to = edge[i].to; 38 if(!dfn[to]) { 39 dfs(to); 40 low[u] = min(low[u], low[to]); 41 if(low[to] > dfn[u]) {//表示找到一个连通块 42 type++; 43 int v; 44 do { 45 v = st[top--]; 46 belo[v] = type;//表示v属于第type个连通块 47 } while(v != to); 48 geedge[++getot].u = u;//记录割边的起点 49 geedge[getot].to = to;//记录割边的另一个点 50 } 51 } 52 else 53 low[u] = min(low[u], low[to]); 54 } 55 } 56 void DFS(int len,int fa,int now){//求树的直径 57 if(len>ans){ 58 ans=len; 59 start=now; 60 } 61 for(int i=head[now];i!=-1;i=edge[i].next){ 62 int v=edge[i].to; 63 if(v!=fa) DFS(len+1,now,v); 64 } 65 } 66 int main(){ 67 while(~scanf("%d%d",&n,&m)&&n){ 68 init(); 69 for(int i=1;i<=m;i++){ 70 scanf("%d%d",&u,&v); 71 add(u,v); 72 add(v,u); 73 } 74 for(int i=1;i<=n;i++) 75 if(!dfn[i]) 76 dfs(i); 77 ans1=getot; 78 memset(head,-1,sizeof(head));cnt=0;//刷新边,接下来从新加边 79 for(int i=1;i<=ans1;i++){ 80 add(belo[geedge[i].to],belo[geedge[i].u]); 81 add(belo[geedge[i].u],belo[geedge[i].to]); 82 } 83 ans = 0; 84 DFS(0,-1,1);// 85 ans=0; 86 DFS(0,-1,start);//两遍DFS求树的直径 87 printf("%d ", getot-ans); 88 } 89 }