HDU - 4009-Transfer water (最小树形图)

时间:2021-09-25 16:01:32

题目链接:HDU - 4009-Transfer water

最小树形图模板。
二重循环下标写同样的WA了好久。。。

#include<bits/stdc++.h>
using namespace std;
int n,x,y,z,m;
const int maxn=1007;
const int INF=2e9+7;
struct Edge{
int u,v;
int d;
};
Edge edges[maxn*(maxn+1)];
int a[maxn],b[maxn],c[maxn],pre[maxn],vis[maxn],id[maxn],in[maxn];
void addedge(int u,int v,int d)
{
edges[m].u=u;
edges[m].v=v;
edges[m].d=d;
m++;
}
int dis(int u,int v)
{
return abs(a[u]-a[v])+abs(b[u]-b[v])+abs(c[u]-c[v]);
}
int zhuliu(int rt,int n,int m)
{
int res=0;
while(1)
{
for(int i=0;i<n;i++) in[i]=INF;
for(int i=0;i<m;i++)
if(edges[i].u!=edges[i].v&&in[edges[i].v]>edges[i].d)
in[edges[i].v]=edges[i].d,pre[edges[i].v]=edges[i].u;
memset(vis,-1,sizeof(vis));
memset(id,-1,sizeof(id));
int tn=0;
in[rt]=0;
for(int i=0;i<n;i++)
{
int u=i;
res+=in[u];
while(u!=rt&&id[u]==-1&&vis[u]!=i)
{
vis[u]=i;
u=pre[u];
}
if(u!=rt&&id[u]==-1)
{
for(int v=pre[u];v!=u;v=pre[v]) id[v]=tn;
id[u]=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;)
{
int v=edges[i].v;
edges[i].u=id[edges[i].u];
edges[i].v=id[edges[i].v];
if(edges[i].u!=edges[i].v)
edges[i++].d-=in[v];
else edges[i]=edges[--m];
}
rt=id[rt];
n=tn;
}
return res;
}

int main()
{
while(~scanf("%d%d%d%d",&n,&x,&y,&z))
{
if(n==0) break;
m=0;
for(int i=1;i<=n;i++) scanf("%d%d%d",&a[i],&b[i],&c[i]);
for(int i=1;i<=n;i++)
{
int k;
scanf("%d",&k);
for(int j=0;j<k;j++)
{
int v;
scanf("%d",&v);
addedge(i,v,dis(i,v)*y+(c[i]<c[v]?z:0));
}
}
for(int i=1;i<=n;i++) addedge(0,i,c[i]*x);
printf("%d\n",zhuliu(0,n+1,m));
}
return 0;
}