POJ-3498-March of the Penguins
2013-08-03 15:57
405 查看
这个题是说有一些冰块,每个冰块上都有些企鹅,同时每个冰块上企鹅只能跳k次,给出企鹅能跳的最大距离,需要求出企鹅能在那些冰块上相遇。
思路:
1、建立初始点和汇点,枚举每个点作为聚结点。
2、拆分点(将A拆分为A和A',若AB能够相连,则分别连接A’->B,B'->A,权值赋为无穷。将起点与每个点建立连接,权值为每个冰块最开始所有的企鹅数,将每个点与它的拆点进行连接,权值为该冰块所允许的最大跳跃次数,然后对于枚举的汇聚点,修改该点与拆点的权值为无穷,然后再将它与汇点连接,权值为无穷。
3、建图完毕后,用Dinic/ISAP跑网络流即可,若得到的值等于企鹅的数量,则该点可以作为汇聚点。
代码:
思路:
1、建立初始点和汇点,枚举每个点作为聚结点。
2、拆分点(将A拆分为A和A',若AB能够相连,则分别连接A’->B,B'->A,权值赋为无穷。将起点与每个点建立连接,权值为每个冰块最开始所有的企鹅数,将每个点与它的拆点进行连接,权值为该冰块所允许的最大跳跃次数,然后对于枚举的汇聚点,修改该点与拆点的权值为无穷,然后再将它与汇点连接,权值为无穷。
3、建图完毕后,用Dinic/ISAP跑网络流即可,若得到的值等于企鹅的数量,则该点可以作为汇聚点。
代码:
#include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<cmath> using namespace std; const int inf=1<<29; const int maxn=210; const int maxm=5e5; struct Pole { int x; int y; int s; int w; }a[110]; int n,e,st,des,head[maxn],pnt[maxm],nxt[maxm],flow[maxm],level[maxn]; double d,dis[110][110]; queue<int> q; double Dis(int i,int j) { return sqrt(1.0*(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y)); } void AddEdge(int u,int v,int f) { pnt[e]=v;nxt[e]=head[u];flow[e]=f;head[u]=e++; pnt[e]=u;nxt[e]=head[v];flow[e]=0;head[v]=e++; } bool BFS() { memset(level,0,sizeof(level)); level[st]=1; q.push(st); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=nxt[i]) if(flow[i]&&!level[pnt[i]]) { level[pnt[i]]=level[u]+1; q.push(pnt[i]); } } return level[des]; } int DFS(int u,int maxf) { if(u==des||!maxf) return maxf; for(int i=head[u],t;i!=-1;i=nxt[i]) if(level[pnt[i]]==level[u]+1&&(t=DFS(pnt[i],min(maxf,flow[i])))) { flow[i]-=t; flow[i^1]+=t; return t; } return level[u]=0; } int maxflow() { int ans=0; while(BFS()) while(1) { int val=DFS(st,inf); if(!val) break; ans+=val; } return ans; } void Build(int val) { e=st=0;des=2*n+1; memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++) { AddEdge(st,i,a[i].s); } for(int i=1;i<=n;i++) { if(val==i) AddEdge(i,n+i,inf); else AddEdge(i,n+i,a[i].w); for(int j=i+1;j<=n;j++) if(dis[i][j]<=d) { AddEdge(n+i,j,inf); AddEdge(n+j,i,inf); } } } int main() { int T; scanf("%d",&T); while(T--) { int sum=0; scanf("%d%lf",&n,&d); for(int i=1;i<=n;i++) { scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].s,&a[i].w); sum+=a[i].s; } for(int i=1;i<=n;i++) for(int j=1;j<i;j++) dis[i][j]=dis[j][i]=Dis(i,j); bool is=true,first=true; for(int i=1;i<=n;i++) { Build(i); AddEdge(n+i,des,inf); int ans=maxflow(); if(ans==sum) { is=false; if(first) { printf("%d",i-1); first=false; } else printf(" %d",i-1); } } if(is) printf("-1"); printf("\n"); } return 0; }
相关文章推荐
- POJ 3498 March of the Penguins(枚举+最大流)
- POJ 3498 March of the Penguins
- poj 3498 March of the Penguins 点流量有限制的最大流
- poj 3498 March of the Penguins(最大流+拆点)
- [POJ 3498] March of the Penguins
- POJ 3498 —— March of the Penguins (枚举+最大流)
- POJ 3498 March of the Penguins(网络最大流)
- POJ 3498 March of the Penguins
- poj 3498(March of the Penguins)
- POJ - 3498 March of the Penguins 最大流(拆点 + 枚举汇点)
- POJ 3498 March of the Penguins(枚举+最大流)
- POJ 3498 - March of the Penguins 拆点构图最大流
- POJ 3498 && HDU 2334 March of the Penguins(最大流-Dinic)
- POJ 3498 March of the Penguins
- poj 3498 March of the Penguins(满足点容量限制的网络流)
- poj 3498 March of the Penguins 带点容量限制的做法是拆点,把一个点拆成两个点,他们直接连一条边就是点容量。然后再求最大流
- POJ 3498 March of the Penguins(枚举+最大流)
- POJ 3498 March of the Penguins
- 3498 March of the Penguins //maxflow
- POJ March of the Penguins