zoukankan      html  css  js  c++  java
  • POJ1639顶点度限制最小生成树

    题目:http://poj.org/problem?id=1639

    见汪汀的《最小生成树问题的拓展》。

    大体是先忽略与根节点相连的边,做一遍kruscal,得到几个连通块和一个根节点;

    然后根节点和每个连通块连一条边,当然是尽量小的,这时连的边就是根的最少度;

    然后用增广的思路多给根连边,具体证明见论文;当最优的交换值也是负的时候break。

    每次都要从根开始重弄dp值是因为要赋一遍初值。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>//
    #include<algorithm>
    #include<map>
    using namespace std;
    typedef long long ll;
    const int N=250;
    const ll INF=0x7fffffff;
    int n,m,K,s,fa[N],xnt,tmp[N],rd,rnt;
    bool b[N][N];
    ll f[N][N],d[N],ans;
    map<string,int> mp;
    struct Bh{
        int x,y;
        Bh(int a=0,int b=0):x(a),y(b) {}
    }bh[N],r[N];
    bool cmp(int a,int b){return f[s][a]<f[s][b];}
    bool cmp2(Bh a,Bh b){return f[a.x][a.y]<f[b.x][b.y];}
    int find(int a)
    {
        if(fa[a]==a)return a;
        return fa[a]=find(fa[a]);
    }
    void dfs(int cur,int fa)
    {
    //    printf("(%d)",cur);
        for(int i=1;i<=n;i++)
            if(b[cur][i]&&i!=fa)
            {
                if(d[i]<d[cur])d[i]=d[cur],bh[i]=bh[cur];
                if(d[i]<f[cur][i])d[i]=f[cur][i],bh[i]=Bh(cur,i);
                dfs(i,cur);
            }
    }
    int main()
    {
        scanf("%d",&m);
        memset(f,1,sizeof f);
        string x,y;ll z;
        for(int i=1;i<=m;i++)
        {
            cin>>x>>y>>z;//
            if(!mp[x])mp[x]=++n;if(!mp[y])mp[y]=++n;
            f[mp[x]][mp[y]]=f[mp[y]][mp[x]]=min(f[mp[x]][mp[y]],z);
            
        }
        s=mp["Park"];
        scanf("%d",&K);
        for(int i=1;i<=n;i++)
        {
            fa[i]=i;
            for(int j=i+1;j<=n;j++)
                if(f[i][j]<INF)r[++rnt]=Bh(i,j);
        }
        sort(r+1,r+rnt+1,cmp2);        //
        for(int u=1,i,j;u<=rnt;u++)
            if(find(i=r[u].x)!=find(j=r[u].y)&&i!=s&&j!=s)
            {
                fa[find(i)]=find(j);
                b[i][j]=b[j][i]=1;
            }
        for(int i=1;i<=n;i++)
            if(f[s][i]<INF&&i!=s)tmp[++xnt]=i;
        sort(tmp+1,tmp+n,cmp);
        for(int i=1,v;i<=n;i++)
            if(find(v=tmp[i])!=s)
            {
                fa[find(v)]=s;
                b[v][s]=b[s][v]=1;
                rd++;
            }
        memset(d,-2,sizeof d);
        dfs(s,0);
        for(;rd<=K;rd++)
        {
            ll mx=-INF;int u=0;
            for(int i=1,v;i<=xnt;i++)
                if(!b[v=tmp[i]][s]&&f[bh[v].x][bh[v].y]-f[s][v]>mx)
                    mx=f[bh[v].x][bh[v].y]-f[s][v],u=v;
                if(mx<=0)break;//
                b[s][u]=b[u][s]=1;
                b[bh[u].x][bh[u].y]=b[bh[u].y][bh[u].x]=0;
                memset(d,-2,sizeof d);//
                dfs(s,0);
        }
        for(int i=1;i<n;i++)
            for(int j=i+1;j<=n;j++)
                ans+=b[i][j]?f[i][j]:0;
        printf("Total miles driven: %lld",ans);
        return 0;
    }
  • 相关阅读:
    阿里云磁盘扩容
    【Vue】WebPack 忽略指定文件或目录
    MySQL 全文索引 (FullText)
    产品设计
    13-Java面向对象-抽象类与接口
    06-数据存储
    07-网络与通信-02-Android中基于HTTP的通信技术
    10-Android 广播接收器 BroadcastReceiver
    09-Android 中 AIDL 的理解与使用
    09-Android 中 AIDL 的理解与使用
  • 原文地址:https://www.cnblogs.com/Narh/p/8800759.html
Copyright © 2011-2022 走看看