POJ3489企鹅
1974: 企鹅
时间限制: 1 Sec 内存限制: 128 MB提交: 31 解决: 15
[提交][状态][讨论版]
题目描述
在靠近南极的某处,一些企鹅站在许多漂浮的冰块上。由于企鹅是群居动物,所以它们想要聚集到一起,在同一个冰块上。企鹅们不想把自己的身体弄湿,所以它们在冰块之间跳跃,但是它们的跳跃距离,有一个上限。
随着气温的升高,冰块开始融化,并出现了裂痕。而企鹅跳跃的压力,使得冰块的破裂加速。幸运的是,企鹅对冰块十分有研究,它们能知道每块冰块最多能承受多少次跳跃。对冰块的损害只在跳起的时候产生,而落地时并不对其产生伤害。
现在让你来帮助企鹅选择一个冰面使得它们可以聚集到一起。
Input
输入
第一行整数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
提示
样例2: 3 1.1 -1 0 5 10 0 0 3 9 2 0 1 1
1
裂点,把点权转化为边权,一个点裂成两个点,就可以把限制转化为这条边上的流量限制
模板里cnt是从2开始的,调了1个上午
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #define INF 1<<28 #define s 0 using namespace std; int n,penguin_num,ans,cnt=1,head[205],T,level[205],q[205]; double d; struct note{ int x,y,num,limit; }rock[105]; struct data{ int to,next,v; }e[40005],e1[40005]; void ins(int u,int v,int w) {e[++cnt].to=v;e[cnt].next=head[u];e[cnt].v=w;head[u]=cnt;} void add_way(int u,int v,int w) {ins(u,v,w);ins(v,u,0);} bool check(int a,int b) { return (rock[a].x-rock[b].x)*(rock[a].x-rock[b].x)+(rock[a].y-rock[b].y)*(rock[a].y-rock[b].y)<=d*d; } bool bfs() { int t=0,w=1,i,now; memset(level,-1,sizeof(level)); q[0]=0;level[0]=0; while(t<w) { now=q[t];t++;i=head[now]; while(i) { if(e[i].v&&level[e[i].to]==-1) { level[e[i].to]=level[now]+1; q[w++]=e[i].to; } i=e[i].next; } } return level[T]==-1? 0:1; } int dfs(int x,int f) { if(x==T) return f; int w,used=0,i; i=head[x]; while(i) { if(e[i].v&&level[e[i].to]==level[x]+1) { w=f-used; w=dfs(e[i].to,min(w,e[i].v)); e[i].v-=w; e[i^1].v+=w; used+=w; if(used==f) return f; } i=e[i].next; } if(!used) level[x]=-1; return used; } void dinic() { ans=0; for(int i=1;i<=cnt;i++) e[i]=e1[i]; while(bfs()) { ans+=dfs(s,INF); } } int main() { scanf("%d %lf",&n,&d); for(int i=1;i<=n;i++) { scanf("%d %d %d %d",&rock[i].x,&rock[i].y,&rock[i].num,&rock[i].limit); add_way(s,i,rock[i].num); add_way(i,i+n,rock[i].limit); penguin_num+=rock[i].num; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j&&check(i,j)) { add_way(i+n,j,1<<28); } for(int i=1;i<=cnt;i++) e1[i]=e[i]; bool flag=0; for(T=1;T<=n;T++) { dinic(); if(ans==penguin_num) { if(!flag) printf("%d",T-1);else printf(" %d",T-1); flag=1; } } if(!flag) printf("%d\n",-1);else cout<<endl; return 0; }