http://acm.hdu.edu.cn/showproblem.php?pid=4009
怎么10年前区域赛这么板的啊,而且数值大小也不说,k的总和也不说,要真跑满过不了的啊
这题有个坑就是他说的曼哈顿距离其实是包括高度的,我看高度用来判断要不要一个水泵就直接以为只要看a,b了,没想到c的曼哈顿距离也要算进去
然后挖坑就是超级源点连到每一个点,边就算一下权值判一下高度就行,然后贴个最小树形图就行了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=1e6+1010;
const ll inf=1ll<<60;
int n,m,x,y,z;ll ans;
int pre[maxl],vis[maxl],id[maxl];
ll ine[maxl];
struct cor
{
int a,b,c;
}a[maxl];
struct ed
{
int u,v;ll w;
}e[maxl];
inline void prework()
{
n++;
for(int i=2;i<=n;i++)
scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c);
m=0;
for(int i=2;i<=n;i++)
{
e[++m]=ed{1,i,1ll*x*a[i].c};
int k;scanf("%d",&k);
for(int j=1;j<=k;j++)
{
int v;scanf("%d",&v);v++;
ll l=1ll*(abs(a[v].a-a[i].a)+abs(a[v].b-a[i].b)+abs(a[v].c-a[i].c))*y;
if(a[v].c>a[i].c)
l+=z;
e[++m]=ed{i,v,l};
}
}
}
inline ll zhuliu()
{
ll ans=0;int rt=1;
while(1)
{
for(int i=1;i<=n;i++) ine[i]=inf;
for(int i=1;i<=m;i++)
{
int u=e[i].u,v=e[i].v;
if(u!=v && e[i].w<ine[v])
ine[v]=e[i].w,pre[v]=u;
}
for(int i=1;i<=n;i++)
if(i!=rt && ine[i]==inf)
return -1;
int cnt=0;
for(int i=1;i<=n;i++)
vis[i]=id[i]=0;
for(int i=1;i<=n;i++)
{
if(i==rt) continue;
ans+=ine[i];
int v=i;
while(vis[v]!=i && !id[v] && v!=rt)// find circle
{
vis[v]=i;
v=pre[v];
}
if(!id[v] && v!=rt)//circle to point
{
id[v]=++cnt;
for(int u=pre[v];u!=v;u=pre[u])
id[u]=cnt;
}
}
if(cnt==0) break;//no circle
for(int i=1;i<=n;i++)
if(!id[i])
id[i]=++cnt;
for(int i=1;i<=m;i++)
{
int u=e[i].u,v=e[i].v;
e[i].u=id[u],e[i].v=id[v];
if(id[u]!=id[v])//ine[v] add to ans, more edge = del original edge
e[i].w-=ine[v];
}
rt=id[rt];n=cnt;
}
return ans;
}
inline void mainwork()
{
ans=zhuliu();
}
inline void print()
{
if(ans<0)
puts("poor XiaoA");
else
printf("%lld\n",ans);
}
int main()
{
while(~scanf("%d%d%d%d",&n,&x,&y,&z))
{
if(n==0 && x==0 && y==0 && z==0)
break;
prework();
mainwork();
print();
}
return 0;
}