企鹅----sap+裂点

企鹅

题目描述

在靠近南极的某处,一些企鹅站在许多漂浮的冰块上。由于企鹅是群居动物,所以它们想要聚集到一起,在同一个冰块上。企鹅们不想把自己的身体弄湿,所以它们在冰块之间跳跃,但是它们的跳跃距离,有一个上限。 
随着气温的升高,冰块开始融化,并出现了裂痕。而企鹅跳跃的压力,使得冰块的破裂加速。幸运的是,企鹅对冰块十分有研究,它们能知道每块冰块最多能承受多少次跳跃。对冰块的损害只在跳起的时候产生,而落地时并不对其产生伤害。 
现在让你来帮助企鹅选择一个冰面使得它们可以聚集到一起。 

输入

第一行整数N,和浮点数D,表示冰块的数目和企鹅的最大跳跃距离。 

(1≤N ≤100) (0 ≤D ≤100 000), 
接下来N行,xi, yi, ni and mi,分别表示冰块的X和Y坐标,该冰块上的企鹅数目,以及还能承受起跳的次数。 

输出

输出所有可能的相聚冰块的编号,以0开始。如果不能相遇,输出-1。

样例输入

5 3.5
1 1 1 1
2 3 0 1
3 5 1 1
5 1 1 1
5 4 0 1

样例输出

1 2 4

题解:

这应该是一道网络流的经典应用。。

每个点上有企鹅,但也有起跳限制,我们可以把这些看作流量。。

将i拆成i和n+i,n+i是可起跳点,i是可跳到的点。。

设一个超级源点src,则一开始

add(src,i,c)//c为企鹅数

add(i,i+n,d)//d为起跳限制

如果两块冰的距离小于限制,也可以连边。

 

#include<stdio.h>
#include<iostream>
using namespace std;
const int N=205;
double d;
int n,m,i,ans,sum,x,y,j,p,src,tar,dis[N],gap[N],a[N],b[N],c[N];
int tot,head[N],Next[60005],to[60006],v[60005],len[60005];
void add(int x,int y,int z)
{
    to[tot]=y;
    v[tot]=z;
    len[tot]=z;
    Next[tot]=head[x];
    head[x]=tot++;
}
inline int isap(int x,int s)
{
    if(x==tar) return s;
    int flow=0,Min=n-1,i;
    for(i=head[x];i!=-1;i=Next[i])
    {
        int y=to[i];
        if(v[i]>0)
        {
            if(dis[x]==dis[y]+1)
            {
                int tmp=isap(y,min(s-flow,v[i]));
                flow+=tmp;
                v[i]-=tmp;
                v[i^1]+=tmp;
            }
            Min=min(Min,dis[y]);
        }
        if(flow==s) return flow;
        if(dis[src]==n) return flow;
    }
    if(flow==0)
    {
        gap[dis[x]]--;
        if(gap[dis[x]]==0) dis[src]=n;
        dis[x]=Min+1;
        gap[dis[x]]++;
    }
    return flow;
}
int main()
{
    scanf("%d%lf",&m,&d);
    n=m*2+1;src=n;
    for(i=1;i<=n;i++) head[i]=-1;
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&a[i],&b[i],&x,&y);
        sum+=x;
        add(n,i,x);add(i,n,0);
        add(i,i+m,y);add(i+m,i,0);
        for(j=1;j<i;j++)
            if(1.0*((a[i]-a[j])*(a[i]-a[j])+(b[i]-b[j])*(b[i]-b[j]))<=d*d)
        {
            add(m+i,j,1e9);add(j,m+i,0);
            add(m+j,i,1e9);add(i,m+j,0);
        }
    }
    for(i=1;i<=m;i++)
    {
        gap[0]=n;
        for(j=1;j<=n;j++) gap[j]=dis[j]=0;
        for(j=0;j<tot;j++) v[j]=len[j];
        ans=0;tar=i;
        while(dis[n]<n)
            ans+=isap(n,1e9);
        if(ans==sum)
        {
            if(p) printf(" ");
            p=1;
            printf("%d",i-1);
        }
    }
    if(p==0) printf("-1");
    return 0;
}

 

  

 

posted @ 2016-07-17 13:39  lwq12138  阅读(262)  评论(0编辑  收藏  举报