hdu 5452 Minimum Cut
http://acm.hdu.edu.cn/showproblem.php?pid=5452
题意:给出一张图和他的一颗生成树,删去最少的边,使图不连通。
删的边中要求有且仅有一条是给定生成树中的边。
删去一条树边以及能和这条树边构成环的非树边,图不连通
所以树上差分,非树边的两个端点+1,lca-2
统计树上后缀和得能与该树边构成环的非树边条数
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 20001 #define M 200001 int front[N],to[M<<1],nxt[M<<1],tot; int dd,fa[N][16]; int dfn,id[N]; int sum[N]; void add(int u,int v) { to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; } void dfs(int u,int f) { id[u]=++dfn; for(int i=1;i<=dd;++i) fa[u][i]=fa[fa[u][i-1]][i-1]; for(int i=front[u];i;i=nxt[i]) if(to[i]!=f) { fa[to[i]][0]=u; dfs(to[i],u); } } int get_lca(int u,int v) { if(u==v) return u; if(id[u]<id[v]) swap(u,v); for(int i=dd;i>=0;--i) if(id[fa[u][i]]>id[v]) u=fa[u][i]; return fa[u][0]; } void dfs2(int x) { for(int i=front[x];i;i=nxt[i]) if(to[i]!=fa[x][0]) { dfs2(to[i]); sum[x]+=sum[to[i]]; } } int main() { int T,n,m,u,v,ans; scanf("%d",&T); for(int t=1;t<=T;++t) { scanf("%d%d",&n,&m); dd=log(n)/log(2)+1; tot=0; memset(front,0,sizeof(front)); for(int i=1;i<n;++i) { scanf("%d%d",&u,&v); add(u,v); } dfn=0; memset(fa,0,sizeof(fa)); dfs(1,0); memset(sum,0,sizeof(sum)); for(int i=n;i<=m;++i) { scanf("%d%d",&u,&v); sum[u]++; sum[v]++; sum[get_lca(u,v)]-=2; } dfs2(1); ans=m-n+2; for(int i=2;i<=n;++i) ans=min(ans,sum[i]+1); printf("Case #%d: %d\n",t,ans); } return 0; }