zoukankan      html  css  js  c++  java
  • cdqz2017-test11-奇诺之旅(拟阵)

    解为基环树森林

    证明其具有拟阵的性质:

    1、空集独立

    2、基环树森林的子集仍然是基环树森林,满足遗传特性

    3、对于基环树森林A,B,若|A|<|B| (边数),一定可以找到一条边e∈B,∉A,使A∪e仍然是基环树森林,满足扩充特性

    扩充特性证明:

    枚举A中的联通块

    1、若A中这个联通块的边数<B中对应联通块的边数,显然存在一条满足要求的边

    2、否则B中存在一条边连接了A的两个联通块。枚举B中这样的边,若这两个联通块至少有一个不是基环树,则该边满足要求。

    否则,A中这两个联通块都是基环树,B中不是基环树,因此B中这个联通块的边数<A中这两个联通块的边数和。所以还存在其他的联通块之间的边满足要求

    所以本题解法:

    按边权从大到小排序,先构造出一颗最大权值基环树

    然后按边权从大到小枚举之前没有用过的边u--v

    首先明确不会存在原来联通块是树,加上这条边变成基环树的情况

    因为之前已经构造了最大权值基环树

    1、若u和v在同一个联通块,该联通块一定是基环树,那么新加的这条边可以替换环上的任意一条边,也可以替换u和v到环的路径上的一条边

    2、若u和v不在同一个联通块,那么这两个联通块都是基环树,这条边可以替换两个环上的任意一条边,也可以替换u和v到环的路径上的一条边

    无论哪种情况,都是用当前边去替换最大权值基环树上的边

    遇上已经被替换过一次的边则停止替换,因为之前用的边的边权不会比现在的边的边权小

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    typedef long long LL;
    
    #define N 200001
    
    struct node
    {
        int u,v,w;
        int id;
        bool use;
    }e[N];
    
    LL ans[N];
    
    int fa[N],siz_p[N],siz_e[N];
    int circle[N];//基环的环在哪儿 
    
    struct graph
    {
        int from,to,id,w;
        int nxt;
    }g[N<<1];
    int tot,front[N];
    int pre[N];
    
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    bool cmp(node p,node q)
    {
        return p.w>q.w;
    }
    
    int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); }
    
    void unionn(int u,int v)
    {
        int fu=find(u),fv=find(v);
        if(fu==fv)
        {
            circle[fu]=u;
            siz_e[fu]++;
            return;
        }
        fa[fu]=fv;
        siz_e[fv]+=siz_e[fu]+1;
        siz_p[fv]+=siz_p[fu];
        circle[fv]|=circle[fu];
    }
    
    void add(int u,int v,int t)
    {
        g[++tot].from=u; g[tot].to=v; g[tot].id=e[t].id; g[tot].w=e[t].w; g[tot].nxt=front[u]; front[u]=tot;
        g[++tot].from=v; g[tot].to=u; g[tot].id=e[t].id; g[tot].w=e[t].w; g[tot].nxt=front[v]; front[v]=tot;
    }
    
    int dfs(int now,int last)
    {
        int tmp=0,t;
        for(int i=front[now];i;i=g[i].nxt)
        {
            t=g[i].to;
            if(t==last) continue;
            if(pre[t]==-1) tmp=i;
            if(pre[t]) continue;
            pre[t]=i;
            tmp|=dfs(t,now);
        }
        return tmp;
    }
    
    void concat(int x,int w)
    {
        int now;
        while(1)
        {
            now=pre[x];
            if(ans[g[now].id]) break;
            ans[g[now].id]=ans[0]-g[now].w+w;
            x=g[now].from;
        }
    }
    
    void out(LL x)
    {
        if(x>9) out(x/10);
        putchar(x%10+'0');
    } 
    
    int main()
    {
        freopen("journey.in","r",stdin);
        freopen("journey.out","w",stdout);
        int n,m;
        read(n); read(m);
        for(int i=1;i<=m;++i) 
        {
            read(e[i].u); read(e[i].v); read(e[i].w);
            e[i].id=i;
        }
        sort(e+1,e+m+1,cmp);
        for(int i=1;i<=n;++i)
        {
            fa[i]=i;
            siz_p[i]=1;
        }
        int fu,fv;
        for(int i=1;i<=m;++i)
        {
            fu=find(e[i].u);
            fv=find(e[i].v);
            if(siz_p[fu]==siz_e[fu] && siz_p[fv]==siz_e[fv]) continue;
            ans[0]+=e[i].w;
            e[i].use=true;
            unionn(e[i].u,e[i].v);
            add(e[i].u,e[i].v,i);
            
        }
        int u;
        for(int i=1;i<=n;++i)
        {
            u=find(i);
            if(circle[u]) u=circle[u];
            if(!pre[u])
            {
                pre[u]=-1;
                pre[u]=dfs(u,-1);
            }
        }
        for(int i=1;i<=m;++i)
        {
            if(e[i].use) continue;
            ans[e[i].id]=ans[0];
            concat(e[i].u,e[i].w);
            concat(e[i].v,e[i].w);
        }
        for(int i=1;i<=m;++i)
            if(!ans[e[i].id]) ans[e[i].id]=ans[0]-e[i].w;
        for(int i=1;i<=m;++i) out(ans[i]),putchar('
    ');
    }
  • 相关阅读:
    Mysql(11)_Mysql权限与安全
    Mysql(10)_存储过程与流程控制
    Java(43)_AWT事件处理挂关闭生效
    6.实现合同测试用例
    6.测试库优化
    5.案例回顾及编写测试用例
    4.测试案例实现代码库与测试用例V2.0
    3.测试案例实现代码库与测试用例
    markdown语法学习
    1.faker批量随机造数据
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8710568.html
Copyright © 2011-2022 走看看