企鹅
时间限制: 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 "); 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 }