hdu4009最小树形图

多建一个根,连到每一个点,然后花费是建水井的钱

然后跑一边最小树形图即可,这题必定有解,因为可以从根开始到每一点,可以不用判无解的情况

#include<map>
#include<set>
#include<ctime>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<cstdio>
#include<iomanip>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pi acos(-1)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define MIN(a,b) a<b ? a:b

using namespace std;

const double g=10.0,eps=1e-9;
const int N=1000+10,maxn=500000+10,inf=0x3f3f3f3f;

struct edge{
    int u,v,w;
}e[maxn];
struct pe{
    int x,y,z;
}p[N];
int pre[N],in[N],vis[N];
int ans,Hash[N];
int dis(int a,int b)
{
    return abs(p[a].x-p[b].x)+abs(p[a].y-p[b].y)+abs(p[a].z-p[b].z);
}
bool dirmst(int root,int nv,int ne)
{
    ans=0;
    while(1){
        memset(in,inf,sizeof in);
        for(int i=0;i<ne;i++)
        {
            int u=e[i].u,v=e[i].v;
            if(e[i].w<in[v]&&u!=v)
            {
                in[v]=e[i].w;
                pre[v]=u;
            }
        }
        in[root]=0;
        for(int i=0;i<nv;i++)
            if(in[i]==inf)
               return 0;
        int cntnum=0;
        memset(vis,-1,sizeof vis);
        memset(Hash,-1,sizeof Hash);
        for(int i=0;i<nv;i++)
        {
            ans+=in[i];
            int v=i;
            while(vis[v]!=i&&v!=root&Hash[v]==-1)vis[v]=i,v=pre[v];
            if(v!=root&&Hash[v]==-1)
            {
                for(int u=pre[v];u!=v;u=pre[u])
                    Hash[u]=cntnum;
                Hash[v]=cntnum++;
            }
        }
        if(cntnum==0)return 1;
        for(int i=0;i<nv;i++)
            if(Hash[i]==-1)
                Hash[i]=cntnum++;
        for(int i=0;i<ne;i++)
        {
            int v=e[i].v;
            e[i].v=Hash[e[i].v];
            e[i].u=Hash[e[i].u];
            if(e[i].v!=e[i].u)e[i].w-=in[v];
        }
        nv=cntnum;
        root=Hash[root];
    }
    return 1;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,x,y,z;
    while(cin>>n>>x>>y>>z){
        if(n==0&&x==0&&y==0&&z==0)break;
        for(int i=1;i<=n;i++)cin>>p[i].x>>p[i].y>>p[i].z;
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            int k,s;
            cin>>k;
            while(k--){
                cin>>s;
                e[cnt].u=i;
                e[cnt].v=s;
                e[cnt].w=dis(i,s)*y;
                if(p[s].z>p[i].z)e[cnt].w+=z;
                cnt++;
            }
        }
        for(int i=1;i<=n;i++)
        {
            e[cnt].u=0;
            e[cnt].v=i;
            e[cnt].w=x*p[i].z;
            cnt++;
        }
        dirmst(0,n+1,cnt))
        cout<<ans<<endl;
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/acjiumeng/p/7144709.html