• HDU 5624 KK's Reconstruction 最小生成树


    题意:这是bc round 71 div 1 的 1004 直接去看中文题意

    分析:

    首先,一种合法方案对应了原图的一棵生成树。

    我们知道,最小生成树有一个性质是最大边最小。

    因此,我们可以枚举生成树的最小边,去掉比该边小的边后对新图求最小生成树,那么我们所要的最优解一定包含在其中。

    时间复杂度O(Mlog M+M^2*a (N),显然仅仅这个效率是不够的。

    可以发现我们每次枚举后都重新求了最小生成树,事实上这是不必要的。

    考虑从大到小枚举生成树的最小边,我们要做的实际上是每次加入一条边,维护当前图的最小生成树。

    加入一条边时,我们需要判断这条边能否与之前的边构成环。

    I 若能构成环,用该边替代环中最大边一定更优;

    II 若不能构成环,直接加入该边即可。

    找环中最大边可以用DFS 实现。若图中现有的边数为N-1N1,我们就可以更新答案。

    这样,事件复杂度就降到了O(Mlog M+MN)O(MlogM+MN)。

    更高的效率的方法,我们涉及的操作为加边、删边、查询路径最大边,因此可以使用LCT 来维护。

     

    注:我按照题解写了一发,肯定是我手残,没有理解人家的意思,我发现我写出来还没题解上的效率不行的快

    肯定我不行,

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    #include<vector>
    #include<queue>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    const int maxn=2002;
    const int mod=1e9+7;
    const LL INF=INT_MAX;
    int head[maxn],p;
    struct Edge
    {
        LL u,v,next;
        LL w,mark;
        bool operator<(const Edge &e)const
        {
            return w<e.w;
        }
    } edge[30005],o[15005];
    void add(int u,int v,int w)
    {
        edge[p].u=u;
        edge[p].v=v;
        edge[p].w=w;
        edge[p].mark=0;
        edge[p].next=head[u];
        head[u]=p++;
    }
    int fa[maxn];
    int find(int x)
    {
        if(x==fa[x])return x;
        return fa[x]=find(fa[x]);
    }
    LL tmp,vv,_max;
    void dfs(int u,int f,int res)
    {
        if(u==vv)
            tmp=res;
        for(int i=head[u]; ~i; i=edge[i].next)
        {
            if(edge[i].v==f)continue;
            if(edge[i].mark)continue;
            _max=max(_max,edge[i].w);
            int c=res;
            if(res==-1||edge[i].w>edge[c].w)c=i;
            dfs(edge[i].v,u,c);
        }
    }
    int main()
    {
        int T,n,m;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            for(int i=1; i<=m; ++i)
                scanf("%I64d%I64d%I64d",&o[i].u,&o[i].v,&o[i].w);
            sort(o+1,o+1+m);
            for(int i=1; i<=n; ++i)fa[i]=i;
            p=0;
            memset(head,-1,sizeof(head));
            int cnt=0;
            LL ans=INF;
            for(int i=m; i>0; --i)
            {
                tmp=-1,_max=0,vv=o[i].v;
                if(cnt==n-1)
                {
                    dfs(o[i].u,0,-1);
                    ans=min(ans,_max-o[i+1].w);
                }
                int fx=find(o[i].u);
                int fy=find(o[i].v);
                if(fx!=fy)
                {
                    ++cnt;
                    fa[fx]=fy;
                }
                else
                {
                    if(tmp==-1)
                        dfs(o[i].u,0,-1);
                    edge[tmp].mark=edge[tmp^1].mark=1;
                }
                add(o[i].u,o[i].v,o[i].w);
                add(o[i].v,o[i].u,o[i].w);
            }
            if(cnt==n-1)
            {
                _max=0;
                dfs(1,0,-1);
                ans=min(ans,_max-o[1].w);
            }
            if(ans==INF)printf("-1
    ");
            else  printf("%I64d
    ",ans);
        }
        return 0;
    }
    View Code

     

  • 相关阅读:
    MySQL查询出错提示 --secure-file-priv解决方法
    导入csv文件到mysql
    Ubuntu16.04配置phpmyadmin
    TensorFlow安装(Ubuntu 16.04)
    github设置只识别指定类型的文件
    python file operations
    Ubuntu16.04 install flash plugin
    PRML读书笔记——3 Linear Models for Regression
    Ubuntu下查看机器信息
    PRML读书笔记——2 Probability Distributions
  • 原文地址:https://www.cnblogs.com/shuguangzw/p/5184724.html
Copyright © 2020-2023  润新知