1. 程式人生 > >hdu4009最小樹形圖板子題

hdu4009最小樹形圖板子題

code 不存在 for hdu div 如果 span 樹形 print

/*
調了一下午的最小樹形圖,昨天剛剛看懂模板。。
最小樹形圖,就是有向圖的最小生成樹,很神奇==
*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define MAXN 1002
#define INF 0x3f3f3f3f
using namespace std;
struct Node{
    int x,y,z;
}nodes[MAXN];
struct Edge{
    int u,v,w;
}e[MAXN*MAXN];
int tot;
int
dist(int a,int b,int y,int z){ int res=0; res+=abs(nodes[a].x-nodes[b].x)*y+abs(nodes[a].y-nodes[b].y)*y+abs(nodes[a].z-nodes[b].z)*y; if(nodes[a].z<nodes[b].z) res+=z; return res; } int pre[MAXN],id[MAXN],visit[MAXN],in[MAXN]; int zhuliu(int root,int n,int m){ int res=0
,u,v; while(1){ for(int i=0;i<n;i++) in[i]=INF; //建立最小弧集E for(int i=0;i<m;i++) if(e[i].u!=e[i].v && e[i].w<in[e[i].v]){ pre[e[i].v]=e[i].u; in[e[i].v]=e[i].w; } for(int i=0;i<n;i++)
if(i!=root && in[i]==INF) return -1;//不存在最小樹形圖 int tn=0; memset(id,-1,sizeof id); memset(visit,-1,sizeof visit); in[root]=0; for(int i=0;i<n;i++){//找環染色 res+=in[i]; v=i; while(visit[v]!=i && id[v]==-1 && v!=root){ visit[v]=i; v=pre[v]; }//找環 if(v!=root && id[v]==-1){ for(int u=pre[v];u!=v;u=pre[u]) id[u]=tn; id[v]=tn++; }//染色 } if(tn==0)//沒有環 break; for(int i=0;i<n;i++)//給沒有環的點染色 if(id[i]==-1) id[i]=tn++; for(int i=0;i<m;){// v=e[i].v; e[i].u=id[e[i].u]; e[i].v=id[e[i].v]; if(e[i].u!=e[i].v)//如果是在不同的環裏 e[i++].w -= in[v]; else swap(e[i],e[--m]); } n=tn;//剩下tn個點 root=id[root]; } return res; } int main(){ int n,x,y,z,k,v; while(scanf("%d%d%d%d",&n,&x,&y,&z)!=EOF && n){ tot=0; for(int i=1;i<=n;i++) scanf("%d%d%d",&nodes[i].x,&nodes[i].y,&nodes[i].z); for(int u=1;u<=n;u++){ scanf("%d",&k); while(k--){ scanf("%d",&v); e[tot].u=u; e[tot].v=v; e[tot].w=dist(u,v,y,z); tot++; } } int root=0; for(int i=1;i<=n;i++){ e[tot].u=root; e[tot].v=i; e[tot].w=x*nodes[i].z; tot++; } printf("%I64d\n",zhuliu(root,n+1,tot)); } return 0; }

 

hdu4009最小樹形圖板子題