1. 程式人生 > >Minimum Cut HDU - 5452

Minimum Cut HDU - 5452

題意:

給出一個圖G和它的一個生成樹T。

現在要求刪除生成樹上的一條邊和若干條其他邊,使得圖不連通。

求能刪除的最小邊數。

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200010;
const int DEG=20;
struct edge
{
    int v,nxt;
}edge[maxn*2+100];
int
head[maxn],cnt=0; int num[maxn]; void add_edge(int u,int v) { edge[cnt].v=v; edge[cnt].nxt=head[u]; head[u]=cnt++; } int fa[maxn][20]; int deg[maxn]; void bfs(int u) { queue<int>q; q.push(u); deg[u]=0; fa[u][0]=u; while(!q.empty()) { int now=q.front(); q.pop(); for
(int i=1;i<DEG;i++) { fa[now][i]=fa[fa[now][i-1]][i-1]; } for(int i=head[now];i!=-1;i=edge[i].nxt) { int v=edge[i].v; if(v==fa[now][0]) continue; deg[v]=deg[now]+1; fa[v][0]=now; q.push(v); } } } int
lca(int u,int v) { if(deg[u]>deg[v]) swap(u,v); int hu=deg[u],hv=deg[v]; int tu=u,tv=v; for(int det=hv-hu,i=0;det;det>>=1,i++) { if(det&1) tv=fa[tv][i]; } if(tu==tv) return tu; for(int i=DEG-1;i>=0;i--) { if(fa[tu][i]==fa[tv][i]) continue; tu=fa[tu][i]; tv=fa[tv][i]; } return fa[tu][0]; } void dfs(int u,int pre) { int v; for(int i=head[u];i!=-1;i=edge[i].nxt) { v=edge[i].v; if(v==pre) continue; dfs(v,u); num[u]+=num[v]; } } int main () { int t; scanf("%d",&t); int icase=0; while(t--) { ++icase; int n,m; scanf("%d%d",&n,&m); memset(head,-1,sizeof(head)); cnt=0; memset(deg,0,sizeof(deg)); memset(fa,0,sizeof(fa)); memset(num,0,sizeof(num)); for(int i=1;i<n;i++) { int xx,yy; scanf("%d%d",&xx,&yy); add_edge(xx,yy); } bfs(1); for(int i=n;i<=m;i++) { int xx,yy; scanf("%d%d",&xx,&yy); int ans=lca(xx,yy); //printf("%d\n",ans); num[xx]++; num[yy]++; num[ans]-=2; } dfs(1,1); int minn=0x3f3f3f3f; for(int i=2;i<=n;i++) { minn=min(minn,num[i]); } printf("Case #%d: %d\n",icase,minn+1); } }