POJ 3498 March of the Penguins(枚举+最大流)
来源:互联网 发布:二分查找java 编辑:程序博客网 时间:2024/06/05 06:22
POJ 3498 March of the Penguins(枚举+最大流)
http://poj.org/problem?id=3498
题意:
在X,Y坐标系中有N(N<=100)个冰块...有些冰块上有若干只企鹅..每只企鹅一次最多跳M距离..一个冰块在有Mi个企鹅离开..就会消失..问有哪些冰块可以作为集合点..就是所有企鹅都能成功到这个冰块上来.
分析:
首先我们枚举每块冰,看看这块冰如果作为集合点,是否所有企鹅都能到这块冰上.
建图:
把每块冰分成两个点i和i+n. i表示进入i冰块的点(可以有无数企鹅过来,所以从别的冰到i有边,容量为INF) i+n表示从i冰块出去的点(最多只能有Mi企鹅从这跳出去,所以从i到i+n有边,且容量为Mi)
从源点S到i有边(S, i, i点初始企鹅数).
从i到i+n有边(i, i+n, Mi). 表示第i块冰最多只有Mi个企鹅能跳走.
因为i+n表示的是第i个跳走的点,所以如果冰块i和j之间的距离<=企鹅能跳跃的距离M,有边(i+n, j, INF)
假设我们当前枚举第x块冰块作为集合点,那么(x分成x和x+n两个点)x点就是汇点(不是x+n点哦),我们只要计算到x点的流量是否==企鹅总数即可.
注意最后结果输出编号从0计数.
AC代码:
#include<cstdio>#include<cstring>#include<queue>#include<algorithm>#include<vector>#define INF 1e9using namespace std;const int maxn=200+5;struct Edge{ int from,to,cap,flow; Edge(){} Edge(int f,int t,int c,int fl):from(f),to(t),cap(c),flow(fl){}};struct Dinic{ int n,m,s,t; vector<Edge> edges; vector<int> G[maxn]; bool vis[maxn]; int cur[maxn]; int d[maxn]; void init(int n,int s,int t) { this->n=n, this->s=s, this->t=t; edges.clear(); for(int i=0;i<n;i++) G[i].clear(); } void AddEdge(int from,int to,int cap) { edges.push_back( Edge(from,to,cap,0) ); edges.push_back( Edge(to,from,0,0) ); m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BFS() { queue<int> Q; memset(vis,0,sizeof(vis)); vis[s]=true; d[s]=0; Q.push(s); while(!Q.empty()) { int x=Q.front(); Q.pop(); for(int i=0;i<G[x].size();++i) { Edge& e=edges[G[x][i]]; if(!vis[e.to] && e.cap>e.flow) { vis[e.to]=true; d[e.to] = d[x]+1; Q.push(e.to); } } } return vis[t]; } int DFS(int x,int a) { if(x==t || a==0) return a; int flow=0,f; for(int& i=cur[x];i<G[x].size();++i) { Edge& e=edges[G[x][i]]; if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0) { e.flow +=f; edges[G[x][i]^1].flow -=f; flow+=f; a-=f; if(a==0) break; } } return flow; } int max_flow() { int ans=0; while(BFS()) { memset(cur,0,sizeof(cur)); ans+=DFS(s,INF); } return ans; }}DC;struct Node{ double x,y; int n,m; double get_dist(Node& b)const { return ((x-b.x)*(x-b.x)+(y-b.y)*(y-b.y)); }}nodes[maxn];int n,num;//n是冰块数,num是企鹅数double limit;bool A[maxn][maxn];//是否可行矩阵bool solve(int t){ DC.init(n*2+1, 0, t); for(int i=1;i<=n;i++)if(nodes[i].n) DC.AddEdge(0, i, nodes[i].n); for(int i=1;i<=n;i++)if(nodes[i].m) DC.AddEdge(i, i+n, nodes[i].m); for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(A[i][j]) { DC.AddEdge(i+n,j,INF); DC.AddEdge(j+n,i,INF); } return DC.max_flow() == num;}int main(){ int T; scanf("%d",&T); while(T--) { num=0;//企鹅数 scanf("%d%lf",&n,&limit); for(int i=1;i<=n;i++) { scanf("%lf%lf%d%d",&nodes[i].x,&nodes[i].y,&nodes[i].n,&nodes[i].m); num += nodes[i].n;//统计企鹅总数 } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(i==j) A[i][j]=true; else A[i][j]= (nodes[i].get_dist(nodes[j]) <= limit*limit); } vector<int> ans; for(int i=1;i<=n;i++) { if(solve(i)) ans.push_back(i); } if(ans.size()==0) printf("-1\n"); else { for(int i=0;i<ans.size()-1;++i) printf("%d ",ans[i]-1);//输出编号从0计数 printf("%d\n",ans[ans.size()-1]-1); } } return 0;}
0 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 (枚举+最大流)
- UVALive - 3972 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 3498March 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 March of the Penguins
- uva 12125 - March of the Penguins(最大流)
- UVA 12125 - March of the Penguins(最大流)
- uva 12125 March of the Penguins (最大流)
- Delphi 安装ICS
- HDU Bone Collector 2620 01背包
- CentOS平台实现Nagios+NagiosQL监控
- VBA 读取/写入文本文件
- UVa1151&POJ2784--Buy or Build【kruskal+二进制枚举】
- POJ 3498 March of the Penguins(枚举+最大流)
- java的匿名内部类
- 2013成都站F题||hdu4786 并查集 生成树
- 代码块使用方式
- 故事公园-—昆明莲花池
- 打开程序员之门
- Hbase存储架构(整理)<转>
- 基于角色访问控制RBAC(上篇)
- Extjs4带清空功能的ComboBox