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;
}

 

posted @ 2020-02-29 22:13  TRTTG  阅读(140)  评论(0编辑  收藏  举报