zoukankan      html  css  js  c++  java
  • K度限制MST poj 1639

    /*
    k度限制MST:有一个点的度<=k的MST
    poj 1639
    要求1号点的度不超过k 求MST
    我们先把1号点扔掉 跑MST
    假设有sum个连通分支 然后把这sum个分支连到1上
    就得到了一个sum度的MST 
    这里往上连的时候 我们连这个分支里 距离1最近的
    然后我们在1上加一条边 (即加一个度)得到sum+1度的MST
    这里加边的时候 1连出去的每一条边都试一遍 取最小
    假设当前1连到了 i 因为原来是个树 这样一搞就形成一个环
    我们现在要删去环里面最长边 来得到更小的ans
    我么维护dp[x]代表x到1的路径上权值最大的边的信息
    (不包含与1直接相连的边否则删去1的度减1 并不能得到sum+1度的MST)
    关键就是维护这个dp[x]
    每次找sum+i度的MST之前我们从1dp一遍维护到每个点的max(沿着sum+i-1度的MST)
    在树上跑 复杂度就降下来了On可以搞完
    方程是 dp[x]=max(dp[from],G[from][x])
    当新填的边不比找到的max边大的时候停下 
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #define maxn 110
    using namespace std;
    int n,m,k,num,G[maxn][maxn],vis[maxn][maxn],ans,mt[maxn],wh[maxn],sum,fa[maxn];
    map<string,int>f;
    struct node{
        int u,v,t;
    }e[maxn*maxn],dp[maxn*maxn];
    int cmp(const node &A,const node &B){
        return A.t<B.t; 
    }
    void Add(int from,int to,int dis){
        num++;e[num].v=to;
        e[num].u=from;
        e[num].t=dis;
    }
    int find(int x){
        return x==fa[x]?x:fa[x]=find(fa[x]);
    }
    void Dfs(int now,int from){
        for(int i=2;i<=n;i++){
            if(i==from)continue;
            if(vis[now][i]){
                if(dp[i].t!=-1){
                    if(dp[now].t<G[now][i]){
                        dp[i].t=G[now][i];
                        dp[i].u=now;dp[i].v=i;
                    }
                    else dp[i]=dp[now];
                }
                Dfs(i,now);
            }
        }
    }
    void Kur(){
        sort(e+1,e+1+num,cmp);
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++){
            if(e[i].u==1||e[i].v==1)continue; 
            if(find(e[i].u)==find(e[i].v))continue;
            ans+=e[i].t;fa[find(e[i].u)]=find(e[i].v);
            vis[e[i].u][e[i].v]=vis[e[i].v][e[i].u]=1; 
        }
    }
    int main(){
        scanf("%d",&m);f["Park"]=++n;
        string A,B;int t;
        memset(G,-1,sizeof(G));
        for(int i=1;i<=m;i++){
            cin>>A>>B>>t;
            if(f[A]==0)f[A]=++n;if(f[B]==0)f[B]=++n;
            Add(f[A],f[B],t);
            if(G[f[A]][f[B]]==-1)G[f[A]][f[B]]=G[f[B]][f[A]]=t;
            else G[f[A]][f[B]]=G[f[B]][f[A]]=min(t,G[f[A]][f[B]]);
        }
        scanf("%d",&k);
        Kur();memset(mt,127/3,sizeof(mt));
        for(int i=2;i<=n;i++){
            if(G[1][i]!=-1){
                int r=find(i);
                if(G[1][i]<mt[r]){
                    mt[r]=G[1][i];
                    wh[r]=i;
                }
            }
        }
        for(int i=2;i<=n;i++)
            if(mt[i]!=mt[0]){
                sum++;ans+=G[1][wh[i]];
                vis[1][wh[i]]=vis[wh[i]][1]=1;
            }
        //得到最小sum度树
        for(int i=sum+1;i<=k;i++){
            dp[1].t=-1;
            for(int j=2;j<=n;j++){
                if(vis[1][j])dp[i].t=-1;
                else dp[i].t=0;
            }
            Dfs(1,-1);
            int pos,mii=1e9;
            for(int j=2;j<=n;j++){
                if(G[1][j]==-1)continue;
                if(mii>G[1][j]-dp[j].t){
                    pos=j;mii=G[1][j]-dp[j].t;
                } 
            }
            if(mii>=0)break;
            vis[1][pos]=vis[pos][1]=1;
            vis[dp[pos].u][dp[pos].v]=0;
            vis[dp[pos].v][dp[pos].u]=0;
            ans+=mii;
        }
        printf("Total miles driven: %d
    ",ans);
        return 0; 
    }
  • 相关阅读:
    java ppt4
    课后作业 2
    课后作业2
    java ppt题目
    CommandParameter设计
    《大道至简》第二章读后感
    8.多态
    7.接口与继承
    6.数组
    字符串
  • 原文地址:https://www.cnblogs.com/yanlifneg/p/9384664.html
Copyright © 2011-2022 走看看