zoukankan      html  css  js  c++  java
  • hdu5452 树上差分

    hdu5452 Minimum Cut
    传送门
    题意
    有一个包含(n(2leq nleq 20000))个点,(m(n-1leq mleq 200000))条边的无向图,其中前(n-1)条边是树边。删除一些边,并且其中只能包含一条树边,使得图不连通,计算最少删掉的边数
    题解
    除了树边之外,每加一条边就会多形成一个环,对于环内的树边来说,删除其中一条使得图不连通的所要删除的总边数加一,也就是说每条非树边都对环内树边产生贡献。如果非树边所连接的两个顶点是(u)(v),那么这条边对于从(u)(v)的路径上的树边都会增加1的贡献,通过树上差分统计所有非树边的贡献,最后计算树边边权的最小值

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<cmath>
    #include<ctime>
    #include<climits>
    #include<algorithm>
    #define LL long long
    #define PII pair<int,int>
    #define PLL pair<LL,LL>
    #define pi acos(-1.0)
    #define eps 1e-6
    #define lowbit(x) x&(-x)
    using namespace std;
    
    const int maxn=20010,maxm=40010;
    int T,n,m;
    int head[maxn],nxt[maxm],to[maxm],cnt;
    int depth[maxn],fa[maxn][20];
    int diff[maxn],ans[maxn];
    
    void add(int u,int v){
        to[cnt]=v;
        nxt[cnt]=head[u];
        head[u]=cnt++;
    }
    
    void dfs(int u,int f){
        fa[u][0]=f;
        for(int i=head[u];~i;i=nxt[i]){
            int v=to[i];
            if(v!=f){
                depth[v]=depth[u]+1;
                dfs(v,u);
            }
        }
    }
    
    void lca_init(){
        depth[1]=1;
        dfs(1,0);
        for(int j=1;j<=15;j++){
            for(int i=1;i<=n;i++){
                fa[i][j]=fa[fa[i][j-1]][j-1];
            }
        }
    }
    
    int lca(int x,int y){
        if(depth[x]>depth[y]) swap(x,y);
        int d=depth[y]-depth[x];
        for(int i=0;i<=15;i++){
            if((1<<i)&d) y=fa[y][i];
        }
        if(x==y) return x;
        for(int i=15;i>=0;i--){
            if(fa[x][i]!=fa[y][i]){
                x=fa[x][i];
                y=fa[y][i];
            }
        }
        return fa[x][0];
    }
    
    void dfs2(int u,int f){
        ans[u]=diff[u];
        for(int i=head[u];~i;i=nxt[i]){
            int v=to[i];
            if(v==f) continue;
            dfs2(v,u);
            ans[u]+=ans[v];
        }
    }
    
    int main(){
        scanf("%d",&T);
        for(int cas=1;cas<=T;cas++){
            scanf("%d%d",&n,&m);
            memset(head,-1,sizeof(head));
            cnt=0;
            for(int i=1;i<n;i++){
                int x,y;
                scanf("%d%d",&x,&y);
                add(x,y);
                add(y,x);
            }
            lca_init();
            memset(diff,0,sizeof(diff));
            for(int i=n;i<=m;i++){
                int x,y;
                scanf("%d%d",&x,&y);
                int t=lca(x,y);
                diff[x]++;
                diff[y]++;
                if(t!=1) diff[t]-=2;
            }
            dfs2(1,0);
            int res=2e9+10;
            for(int i=1;i<=n;i++) res=min(res,ans[i]+1);
            printf("Case #%d: %d
    ",cas,res);
        }
        return 0;
    }
    
  • 相关阅读:
    HTML
    Linux 入门记录:十一、Linux 用户基础
    Linux 入门记录:十、Linux 下获取帮助
    Linux 入门记录:九、Linux 文件系统挂载管理
    Linux 入门记录:八、Linux 文件系统
    Linux 入门记录:七、fdisk 分区工具
    Linux 入门记录:六、Linux 硬件相关概念(硬盘、磁盘、磁道、柱面、磁头、扇区、分区、MBR、GPT)
    Linux 入门记录:五、vi、vim 编辑器
    Linux 入门记录:四、Linux 系统常用命令
    Linux 入门记录:三、Linux 文件基本操作管理
  • 原文地址:https://www.cnblogs.com/fxq1304/p/13643090.html
Copyright © 2011-2022 走看看