企鹅

时间限制: 1 Sec  内存限制: 128 MB
提交: 21  解决: 12
[提交][状态][讨论版]

题目描述

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

输入

第一行整数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
这道题也算是接触的比较早了,是2015年那个暑假就接触了,那个时候并不会网络流,第一次实现网络流也是比较垃圾的算法,是用O(nm^2)实现的那个算法,然后学历dinic以后发现网络流就明朗了
这道题是一道裂点+枚举汇点的最大流算法就是原点到每个岛一企鹅的数量连一条边,然后再以起跳次数再与另外(新建)一排点连一条边,然后判断距离,可以相互到达就连一条权值为INF的边,方向边
均为0,这样就可以了。
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<queue>
  6 #include<cstring>
  7 using namespace std;
  8  
  9 const int NN=207,INF=1e8+7;
 10  
 11 int n,sum,S,T;
 12 int cnt,head[NN],next[NN*NN],val[NN*NN],rea[NN*NN],tot[NN*NN];
 13 int x[NN],y[NN],dis[NN];
 14 double D;
 15  
 16 void add(int u,int v,int fee)
 17 {
 18     cnt++;
 19     next[cnt]=head[u];
 20     head[u]=cnt;
 21     rea[cnt]=v;
 22     val[cnt]=fee;
 23     tot[cnt]=fee;
 24 }
 25 double cal(int i,int j){return (double)(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);}
 26 bool bfs()
 27 {
 28     memset(dis,-1,sizeof(dis));
 29     dis[S]=0;
 30     queue<int>q;
 31     q.push(S);
 32     while (!q.empty())
 33     {
 34         int u=q.front();
 35         q.pop();
 36         for (int i=head[u];i!=-1;i=next[i])
 37         {
 38             int v=rea[i],cost=val[i];
 39             if (dis[v]==-1&&cost>0)
 40             {
 41                 dis[v]=dis[u]+1;
 42                 if (v==T) return 1;
 43                 q.push(v);
 44             }
 45         }
 46     }
 47     return 0;
 48 }
 49 int dfs(int u,int MM)
 50 {
 51     int res=0;
 52     if (u==T||MM==0) return MM;
 53     for (int i=head[u];i!=-1;i=next[i])
 54     {
 55         int v=rea[i],fee=val[i];
 56         if (dis[v]!=dis[u]+1) continue;
 57         int x=dfs(v,min(MM,fee));
 58         if (x)
 59         {
 60             val[i]-=x,val[i^1]+=x;
 61             MM-=x,res+=x;
 62             if (MM==0) break;
 63         }
 64     }
 65     return res;
 66 }
 67 int dinic()
 68 {
 69     int res=0;
 70     while (bfs())
 71     {
 72         int x=dfs(S,INF);
 73         while (x)
 74         {
 75             res+=x;
 76             x=dfs(S,INF);
 77         }
 78     }
 79     return res;
 80 }
 81 int main()
 82 {
 83     cnt=1;
 84     memset(head,-1,sizeof(head));
 85     scanf("%d%lf",&n,&D);
 86     S=n*2+1,sum=0;
 87     int pg,ci;
 88     for (int i=1;i<=n;i++)
 89     {
 90         scanf("%d%d",&x[i],&y[i]);
 91         scanf("%d%d",&pg,&ci);
 92         sum+=pg;
 93         add(S,i,pg),add(i,S,0);
 94         add(i,i+n,ci),add(i+n,i,0);
 95     }
 96     for (int i=1;i<=n;i++)
 97         for (int j=1;j<=n;j++)
 98             if (cal(i,j)<=D*D&&i!=j) add(i+n,j,INF),add(j,i+n,0);
 99     queue<int>p;
100     for (T=1;T<=n;T++) 
101     {
102         for (int i=1;i<=cnt;i++)
103             val[i]=tot[i];
104         if (dinic()==sum) p.push(T-1);
105     }
106     if (p.empty()) printf("-1\n");
107     else
108     {
109         printf("%d",p.front());
110         p.pop();
111         while (!p.empty())
112          {
113              
114              printf(" %d",p.front());
115              p.pop(); 
116          }
117     }
118 }