题目链接:http://poj.org/problem?id=3498
题意简述:有n个冰块每个冰块上有ni只企鹅,并且每个冰块允许跳出的次数为mi,判定所有的企鹅能不能够跳到一块冰块上去,当冰块之间的距离小于等于d时企鹅才能从一个冰块跳到另一个冰块,若能所有企鹅能够跳到同一个冰块上,那么输出这些冰块(注意这里输出的时候是以0为参考),若没有这样的冰块满足条件则输出-1
自己不入流的分析方法:每个冰块上的企鹅,要流到一个特定的冰块上,每个冰块限制了能够流出的企鹅数,那么我们就可以这样建图新建源点s ,将冰块拆点u、u‘ ,s到u的权值为冰块上初始的企鹅数,u-u’的权值为该冰块允许流出的企鹅数,最后枚举冰块作为汇点
代码:
#include<iostream>
#include<cstdio>
#include <cstring>
using namespace std;
const int inf=0x3f3f3f3f;
const int N = 210;
const int E = 40000;
struct node
{
int x,y,c,w,nxt;
}edge[E];
struct node1
{
double x, y;
int n, m;
}a[110];
int harsh[N];
int e,head[N];
int dep[N],que[N],cur[N];
void addedge(int u,int v,int c)
{
edge[e].x=u;
edge[e].y=v;
edge[e].w=0;
edge[e].nxt=head[u];
edge[e].c=c;
head[u]=e++;
edge[e].x=v;
edge[e].y=u;
edge[e].w=0;
edge[e].nxt=head[v];
edge[e].c=0;
head[v]=e++;
}
int maxflow(int n,int s,int t)
{
int i,j,k,front,rear,top,min,res=0;
while(1)
{
for(i=0;i<=2*n;i++)
if(harsh[i]==1)
dep[i]=-2;
else dep[i]=-1;
front=0;
rear=0;
que[rear++]=s;
dep[s]=0;
while(front!=rear)
{
i=que[front++];
for(j=head[i];j!=-1;j=edge[j].nxt)
if(edge[j].c>edge[j].w&&dep[edge[j].y]==-1)
{
dep[edge[j].y]=dep[i]+1;
que[rear++]=edge[j].y;
}
}
if(dep[t]==-1)
break;
memcpy(cur,head,sizeof(head));
for(i=s,top=0;;)
{
if(i==t)
{
min=inf;
for(k=0;k<top;k++)
if(min>(edge[que[k]].c-edge[que[k]].w))
{
min=edge[que[k]].c-edge[que[k]].w;
front=k;
}
for(k=0;k<top;k++)
{
edge[que[k]].w+=min;
edge[que[k]^1].w-=min;
}
res+=min;
i=edge[que[top=front]].x;
}
for(j=cur[i];cur[i]!=-1;j=cur[i]=edge[cur[i]].nxt)
if(dep[edge[j].y]==dep[i]+1&&edge[j].c>edge[j].w)
break;
if(cur[i]!=-1)
{
que[top++]=cur[i];
i=edge[cur[i]].y;
}
else
{
if(top==0)
break;
dep[i]=-1;
i=edge[que[--top]].x;
}
}
}
return res;
}
double dis(int i, int j)
{
return (a[i].x-a[j].x)*(a[i].x-a[j].x) + (a[i].y -a[j].y)*(a[i].y-a[j].y);
}
int main ()
{
int t;
double d;
int sum,n,i,j;
scanf("%d",&t);
while(t--)
{
scanf("%d%lf",&n,&d);
sum=0;
for(i=1;i<=n;i++)
{
scanf("%lf%lf%d%d",&a[i].x,&a[i].y,&a[i].n,&a[i].m);
sum+=a[i].n;
}
memset(head,-1,sizeof(head));
e = 0;
for(i=1;i<=n;i++)
{
addedge(0,i,a[i].n);
addedge(i,i+n,a[i].m);
}
for(i=1;i<=n;i++)
for(j=i+1;j<=n;j++)
if(dis(i,j)<=d*d)
{
addedge(n+i,j,inf);
addedge(j+n,i,inf);
}
memset(harsh,0,sizeof(harsh));
int tag = 0;
for(i=1;i<=n;i++)
{
harsh[i+n]=1;
int flow = maxflow(n,0,i);
if(flow==sum)
{
tag = 1;
printf("%d ",i-1);
}
harsh[i+n]=0;
for(j=0;j<e;j++)
edge[j].w=0;
}
if(tag==0)
printf("-1\n");
else printf("\n");
}
return 0;
}