poj1639顶点度限制生成树

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

对根的度数有限制的最小生成树;

先忽略根,跑最小生成树,得到几个连通块,再一一与根连上;

然后在限制内用根连出去的边来使生成树更小,这需要枚举边以及用dp维护树上边的dfs序之前最大的一个;

此题用邻接矩阵比较方便。

改了一晚上,终于发现是混淆了n和cnt,cnt才是点数。

邻接表失败版:

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,head[25],ct=1,cnt,ed,fa[25],cost,reg;
char s1[15],s2[15];
map<string,int>mp;
struct N{
    int to,next,w;
    N(int t=0,int n=0,int ww=0):to(t),next(n),w(ww) {}
}edge[50],e[25];
struct NN{
    int v,bh;
}dp[25];
bool use[50],use2[50],lk[25],vis[25];
bool cmp(N x,N y){return x.w<y.w;}
int find(int x)
{
    if(x==fa[x])return x;
    return fa[x]=find(fa[x]);
}
void kruskal()
{
    sort(edge+2,edge+ct+1,cmp);
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=2;i<=ct;i+=2)
    {
        int u=edge[i].to;
        int v=edge[i^1].to;
        if(find(u)!=find(v))
        {
            cost+=edge[i].w;
            fa[find(u)]=find(v);
            use[i]=1;
            use[i^1]=1;
        }
    }
}
void dfs(int x)
{
    vis[x]=1;
    for(int i=head[x];i;i=edge[i].next)
    {
        int u=edge[i].to;
        if(!use[i]||vis[u])continue;
//        printf("u=%d\n",u);
//        printf("x=%d——u=%d\n",x,u);
        if(dp[x].v>edge[i].w)
        {
            dp[u].v=dp[x].v;
            dp[u].bh=dp[x].bh;
        }
        else
        {
//            printf("u=%d x=%d\n",u,x);
            dp[u].v=edge[i].w;
//            printf("dp[%d].v=%d\n",u,dp[u].v);
            dp[u].bh=i;
        }
        dfs(u);
    }
}
void add(int x,int y,int z)
{
    ct++;
    edge[ct].to=y;
    edge[ct].next=head[x];
    edge[ct].w=z;
    head[x]=ct;
}
int main()
{
    scanf("%d",&n);
    mp["Park"]=++cnt;
    for(int i=1;i<=n;i++)
    {
        int x;
        scanf("%s %s",&s1,&s2);
        scanf("%d",&x);
        if(!mp[s1])mp[s1]=++cnt;
        if(!mp[s2])mp[s2]=++cnt;
        if(mp[s1]==1)
        {
            e[++ed].to=mp[s2];
            e[ed].w=x;
            continue;
        }
        if(mp[s2]==1)
        {
            e[++ed].to=mp[s1];
            e[ed].w=x;
            continue;
        }
//        edge[++ct]=(mp[s2],head[mp[s1]],x);head[mp[s1]]=ct;
//        edge[++ct]=(mp[s1],head[mp[s2]],x);head[mp[s2]]=ct;
        add(mp[s2],mp[s1],x);
        add(mp[s1],mp[s2],x);
    }
//    for(int i=2;i<=ct;i++)
//        printf("w=%d to=%d\n",edge[i].w,edge[i].to);
    scanf("%d",&m);
    kruskal();
    sort(e+1,e+ed+1,cmp);
    for(int i=1;i<=ed;i++)
    {
        int u=e[i].to;
        if(!lk[find(u)])
        {
            cost+=e[i].w;
            lk[find(u)]=1;
            use2[i]=1;
            reg++;
        }
    }
    vis[1]=1;
    for(int i=1;i<=ed;i++)
    {
        if(!use2[i])continue;
        dp[e[i].to].v=-1;
        dfs(e[i].to);
    }
//    for(int i=1;i<=n;i++)
//        printf("i=%d v=%d bh=%d\n",i,dp[i].v,dp[i].bh);
//    for(int i=1;i<=n;i++)
//        printf("dp[%d]=%d\n",i,dp[i].v);
    while(reg<m)
    {
        int mx=-10005;
        int d,k;
        for(int i=1;i<=ed&&reg<m;i++)
        {
            if(use2[i])continue;
            int u=e[i].to;
            if(dp[u].v-e[i].w>mx)
            {
                mx=dp[u].v-e[i].w;
//                cout<<dp[u].v<<" "<<e[i].w<<endl;
                d=u;k=i;
            }
        }
//        printf("mx=%d d=%d k=%d\n",mx,d,k);
        if(mx<=0)break;
        cost-=mx;
        use[dp[d].bh]=0;
        use2[k]=1;
        reg++;
        dp[d].v=-1;
        memset(vis,0,sizeof vis);
        vis[d]=1;
        dfs(d);
    }
    printf("Total miles driven: %d\n",cost);
    return 0;
}
失败版

代码如下:

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
#include<string>
using namespace std;
int n,m,ct,cnt,fa[250],cost,reg,key[250],mne[250],inf=0x3f3f3f3f;
string s1,s2;
map<string, int>mp;
struct N{
    int hd,to,w;
}edge[50000];
struct NN{
    int w,u,v;
}dp[50000];
bool in[250][250];
int sid[250][250];
bool cmp(N x,N y){return x.w<y.w;}
int find(int x)
{
    if(x==fa[x])return x;
    return fa[x]=find(fa[x]);
}
void kruskal()
{
    sort(edge+1,edge+ct+1,cmp);
//    for(int i=1;i<=ct;i++)
//        printf("w=%d u=%d v=%d\n",edge[i].w,edge[i].hd,edge[i].to);
    for(int i=1;i<=cnt;i++)fa[i]=i;//
    for(int i=1;i<=ct;i++)
    {
        int u=edge[i].hd;
        int v=edge[i].to;
        if(u==1||v==1)continue;
        if(find(u)!=find(v))
        {
            cost+=edge[i].w;
            fa[find(u)]=find(v);
            in[u][v]=in[v][u]=1;
        }
    }
}
void dfs(int x,int f)
{
    for(int u=2;u<=cnt;u++)
    {
        if(!in[x][u]||u==f)continue;
        if(dp[u].w==-1)
        {
            if(dp[x].w>sid[x][u])
                dp[u]=dp[x];
            else
            {
                dp[u].w=sid[x][u];
                dp[u].u=x;dp[u].v=u;
            }
        }
        dfs(u,x);
    }
}
int main()
{
    scanf("%d",&n);
    mp["Park"]=++cnt;
    memset(sid,0x3f,sizeof sid);
    for(int i=1;i<=n;i++)
    {
        int x;
        cin>>s1>>s2>>x;
        if(!mp[s1])mp[s1]=++cnt;
        if(!mp[s2])mp[s2]=++cnt;
        int m1=mp[s1],m2=mp[s2];//!
        sid[m1][m2]=sid[m2][m1]=min(sid[m1][m2],x);
        edge[++ct].w=x;
        edge[ct].hd=m1;edge[ct].to=m2;
    }
    scanf("%d",&m);
    kruskal();
//    for(int i=1;i<=cnt;i++)
//        for(int j=1;j<=cnt;j++)
//            if(in[i][j])printf("in[%d][%d]=%d\n",i,j,in[i][j]);
//    cout<<cost<<endl;
    memset(mne,0x3f,sizeof mne);
    for(int i=2;i<=cnt;i++)
    {
        if(sid[i][1]==inf)continue;
        int cr=find(i);
        if(mne[cr]>sid[i][1])
        {
            mne[cr]=sid[i][1];
            key[cr]=i;
        }
    }
    for(int i=1;i<=cnt;i++)//
    {
        if(mne[i]==inf)continue;
//        cost+=mne[i];
        cost+=sid[1][key[i]];//
        in[1][key[i]]=in[key[i]][1]=1;
        reg++;
    }
    for(int j=reg+1;j<=m;j++)
    {
        memset(dp,-1,sizeof dp);
        dp[1].w=-inf;
        for(int i=2;i<=cnt;i++)
        {
            if(in[i][1])dp[i].w=-inf;
//            else dp[i].w=-1;
        }
        dfs(1,-1);
        int mn=inf;
        int d;
        for(int i=2;i<=cnt;i++)
        {
//            if(sid[i][1]==inf)continue;
            if(sid[i][1]-dp[i].w<mn)
            {
                mn=sid[i][1]-dp[i].w;
                d=i;
            }
        }
        if(mn>=0)break;
        cost+=mn;
        in[dp[d].u][dp[d].v]=in[dp[d].v][dp[d].u]=0;
        in[1][d]=in[d][1]=1;
    }
    printf("Total miles driven: %d\n",cost);
    return 0;
}

 

posted @ 2018-04-10 01:00  Zinn  阅读(193)  评论(0编辑  收藏  举报