• HDU 5452 Minimum Cut(树链剖分+树差分)


    题意:给你一颗生成树,然后有一些额外的边连接在生成树上的两点,问你最少要割几条边才能使图不连通,割的边中只能有一条生成树上的边,不能少也不能多

    思路:训练没出,现在来补坑。我们稍加思考可以想到对于一颗生成树,我们其余的边相当于覆盖u,v之前的路线,如果你要割u,v之间的生成树的边的话就要多割一条,我们很直接的想到用线段树来维护区间操作,但是这个题在我们训练的时候是会超时的,所以我们改用树差分,因为我们是树链剖分的,树链剖分有一条性质就是我们在剖分的时候重链的编号是连续的,就是这一条性质保证了可以树差分。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    const int maxn=500008;
    
    int a[maxn],sz[maxn],dep[maxn],fa[maxn],top[maxn],son[maxn],head[maxn];
    int w[maxn],num,cnt;
    int c[maxn];
    struct Edge
    {
        int to,next;
    };
    Edge v[maxn*2];
    void init()
    {
        num=0;cnt=0;
        memset(head,-1,sizeof(head));
    }
    void addedge(int x,int y)
    {
        v[cnt].to = y;
        v[cnt].next = head[x];
        head[x] = cnt++;
    }
    void dfs1(int u, int f, int d) {
        dep[u]=d;sz[u]=1;
        son[u]=0;fa[u]=f;
        for(int i=head[u];i!=-1;i = v[i].next){
            int to = v[i].to;
            if(to!=f){
                dfs1(to,u,d+1);
                sz[u]+=sz[to];
                if(sz[son[u]]<sz[to])son[u]=to;
            }
        }
    }
    void dfs2(int u, int tp) {
        top[u]=tp;
        w[u]=++num;
        if(son[u])dfs2(son[u],tp);
        for(int i = head[u];i!=-1;i=v[i].next){
            int to=v[i].to;
            if(to==fa[u]||to==son[u])continue;
            dfs2(to,to);
        }
    }
    void modify(int x,int y)
    {
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            c[w[top[x]]]++;
            c[w[x]+1]--;
            x=fa[top[x]];
        }
        if(x==y)return ;
        if(dep[x]>dep[y])swap(x,y);
        c[w[son[x]]]++;c[w[y]+1]--;
        return ;
    }
    int main()
    {
        int t,n,m,cas=0;
        scanf("%d",&t);
        while(t--){
            init();
            scanf("%d%d",&n,&m);
            int a,b;
            for(int i=1;i<=n-1;i++){
                scanf("%d%d",&a,&b);
                addedge(a,b);
                addedge(b,a);
            }
            dfs1(1,0,1);
            dfs2(1,1);
            memset(c,0,sizeof(c));
            for(int i=1;i<=m-n+1;i++){
                scanf("%d%d",&a,&b);
                modify(a,b);
            }
            for(int i=1;i<=n;i++){
                c[i]+=c[i-1];
            }
            int ans=0x3f3f3f3f;
            for(int i=1;i<=n;i++){
                if(c[i]!=0&&c[i]){
                    ans=min(ans,c[i]);
                }
            }
            printf("Case #%d: %d
    ",++cas,ans+1);
        }
        return 0;
    }
  • 相关阅读:
    企业命令linux下处理实时日志生成另一个实时日志
    排序算法Java(android)安卓中的list对象排序
    项目设置一个类似HTML map标签功能的Android组件
    最大算法【Manacher模板】HDU 3068——求最长回文子串
    类实现java面向对象上:接口
    线程方法Android:异步调用详解
    输入数字实现分页功能(三层)
    对象主题设计模式读书笔记观察者模式
    网站算法石榴算法严厉打击下 网站盈利方向何在
    闭包执行JavaScript中的闭包
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9756949.html
Copyright © 2020-2023  润新知