标签:
Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65768/65768 K (Java/Others)
Total Submission(s): 3986 Accepted Submission(s): 1434
有向,即最小树形图。
那么剩下就是考虑怎么去构图的问题了。
以水源为根,给每个点连一条边 , 边权是 Point[i].z * X
然后每个点连上它的合法点 , U->V .. w = 曼哈顿距离 * Y。
如果 Point[u].z < Point[v].z 要加一个 pomp 。。 费用为 Z , w += Z.
然后跑一次朱刘算法即可
#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> #include <cstring> #include <vector> using namespace std ; typedef long long LL ; const LL inf = 1e18+7; const int N = 1010; const int M = 2000010; struct edge { int u , v ; LL w; } e[M]; struct node { int x , y , z ; } Point[N]; int n , m , p1 , p2 , p3 ; int pre[N] , id[N] , vis[N] ; LL in[N] ; LL zhuliu( int root , int n , int m ) { LL res = 0 , u , v ; while( true ) { for( int i = 0 ; i < n ; ++i ) in[i] = inf ; 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( vis , -1 , sizeof vis ); in[root] = 0 ; for( int i = 0 ; i < n ; ++i ) { res += in[i]; v = i ; while( vis[v] != i && id[v] == -1 && v != root ) { vis[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 ; // no circle 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 ; root = id[root]; } return res ; } inline LL DIS ( int a , int b ) { return 1LL*abs(Point[a].x-Point[b].x)+abs(Point[a].y-Point[b].y)+abs(Point[a].z-Point[b].z); } int main () { #ifdef LOCAL freopen("in.txt","r",stdin); #endif while( ~scanf("%d%d%d%d",&n,&p1,&p2,&p3) ) { if( !n && !p1 && !p2 && !p3 ) break ; int ecnt = 0 ; for( int i = 1 ; i <= n ; ++i ) { scanf("%d%d%d",&Point[i].x,&Point[i].y,&Point[i].z); } for( int i = 1 ; i <= n ; ++i ) { int k , v ; scanf("%d",&k); for( int j = 1 ; j <= k ; ++j ) { scanf("%d",&v); e[ecnt].u = i , e[ecnt].v = v ; e[ecnt].w = DIS(i,v)*p2; if( Point[i].z < Point[v].z ) e[ecnt].w += p3 ; ecnt++ ; } } for( int i = 1 ; i <= n ; ++i ) { e[ecnt].u = 0 , e[ecnt].v = i , e[ecnt].w = (LL)p1 * Point[i].z ; ecnt++ ; } LL ans = zhuliu( 0 , n + 1 , ecnt ); if( ans == -1 ) puts("poor XiaoA"); else printf("%lld\n",ans); } }
HDU 4009 Transfer water(最小树形图)
标签:
原文地址:http://www.cnblogs.com/hlmark/p/4293009.html