標籤:style blog http 2014 os 代碼
題目:
連結:點擊開啟連結
題意:
有n個村莊,要求使得每個村莊都能得到水的最小費用。每個村莊可以通過挖井或從其他村莊修水路獲得水。挖井的費用是房子的高度乘以X,修水道的費用和有向圖邊的起點和終點的高度有關。
思路:
代碼:
#include <iostream>#include <cstdio>#include <cmath>#include <cstring>using namespace std;#define inf 0x3f3f3f3fconst int maxm=1200000;const int maxn=1200;struct point{ int x,y,z;} p[maxn];struct edge{ int u,v,w;} e[maxm];int pre[maxn],id[maxn],vis[maxn],in[maxn];int n,m;void add(int u,int v,int w){ e[m].u=u,e[m].v=v,e[m++].w=w;}int dist(point a,point b){ return abs(a.x-b.x)+abs(a.y-b.y)+abs(a.z-b.z);}int directedMST(int root){ int res=0,nv=n,i; while (1) { for (i=0; i<nv; i++) { in[i]=inf; } for (i=0; i<m; i++) { int u=e[i].u; int v=e[i].v; if (e[i].w<in[v]&&u!=v) { pre[v]=u; in[v]=e[i].w; } } for (i=0; i<nv; i++) { if (i==root)continue; if (in[i]==inf)return -1; } int cntnode=0; memset(id,-1,sizeof(id)); memset(vis,-1,sizeof(vis)); in[root]=0; for (i=0; i<nv; i++) { res+=in[i]; int 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]=cntnode; } id[v]=cntnode++; } } if (cntnode==0) break; for (i=0; i<nv; i++) { if (id[i]==-1)id[i]=cntnode++; } for (i=0; i<m; i++) { int 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]; } } nv=cntnode; root=id[root]; } return res;}int main(void){ //freopen("input.txt","r",stdin); int x,y,z; while(scanf("%d%d%d%d",&n,&x,&y,&z)==4 && (n+x+y+z)) { m=0; n++; for(int i=1; i<n; i++) { scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z); add(0,i,x*p[i].z); } for(int i=1; i<n; i++) { int k,t; scanf("%d",&k); while(k--) { scanf("%d",&t); if(t == i) continue; int cost = dist(p[i],p[t])*y; if(p[t].z > p[i].z) cost += z; add(i,t,cost); } } printf("%d\n",directedMST(0)); } return 0;}
-------------------------------------------------------
戰鬥,從不退縮;奮鬥,永不停歇~~~~~~~