hlg1512March of the Penguins【无向图+拆点】






























March of the Penguins





Time Limit: 2000 MS Memory Limit: 65535 K







Total Submit: 14(7
users)
Total Accepted: 9(6
users)
Rating:  Special Judge: No
Description

Somewhere near the south pole, a number of penguins
are standing on a number of ice floes. Being social
animals, the penguins would like to get together, all on the same floe.
The penguins do not want to get wet, so they have use
their limited jump distance to get together by jumping
from piece to piece. However, temperatures have been high lately, and the
floes are showing cracks, and they get damaged further
by the force needed to jump to another floe.

Fortunately the penguins are real experts on
cracking ice floes, and know exactly how many times a
penguin can jump off each floe before it disintegrates and disappears.
Landing on an ice floe does not damage it. You have to
help the penguins find all floes where they can
meet.


Input
On the first line one positive
number: the number of testcases, at most 100. After that
per
testcase:
? One line with the integer
N(1≤N≤100) and a floating-point number D(0 ≤ D
≤ 100000), denoting the number of ice pieces and the
maximum distance a penguin can jump.
? N
lines, each line containing xi,
yi, ni and mi,
denoting for each ice piece its X and Y coordinate, the
number of penguins on it and the maximum number of times a
penguin can jump off this piece before it disappears
(?10 000≤xi, yi ≤10 000, 0≤ni
≤10,1≤mi ≤200).
Output
Per testcase:
? One
line containing a space-separated list of 0-based indices of the pieces on
which all
penguins can meet. If no such piece exists,
output a line with the single number ?1.
Sample Input
2
5 3.5
1 1 1 1
2 3 0 1
3 5 1
1
5 1 1 1
5 4 0 1
3 1.1
-1 0 5 10
0 0 3 9
2 0 1 1
Sample Output
1 2 4
-1
Source
NWERC2007

大意:有n块冰块,每块冰块上有一定数量企鹅,并且有一定的跳跃次数(jump off)超过这个次数冰块就会碎掉

告诉每块冰块的企鹅数目和跳跃次数,问那些冰块能使所有的企鹅都到达(冰块编号从零开始)

模型:

1、首先这是一个无向图, 所以冰块之间建立路径的时候要件两条路

2、节点有权值(跳跃次数) 所以要拆点

思路:

冰块拆点之间的权值是跳跃次数

若两冰块之间能到达则建立两条路径(s1,t1)(s2,t2)的话  则由t1指向s2 由t2指向s1,权值为无穷

超级源点跟每块冰块的s建立一条路径,权值为企鹅数量

最后依次枚举每个点做汇点的最大流是否等于企鹅数量即可

代码:

  1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <vector>
5 #include <queue>
6 #include <cmath>
7 using namespace std;
8
9 const int maxn = 505;
10 const int INF = 10000000;
11
12 struct Point{
13 int x, y, ni, mi;
14 }point[maxn];
15
16
17 struct Edge
18 {
19 int from, to, cap, flow, flow2;
20 };
21
22 struct ISAP {
23 int n, m, s, t;
24 vector<Edge> edges;
25 vector<int> G[maxn];
26 bool vis[maxn];
27 int d[maxn];
28 int cur[maxn];
29 int p[maxn];
30 int num[maxn];
31
32 void AddEdge(int from, int to, int cap) {
33 edges.push_back((Edge){from, to, cap, 0, 0});
34 edges.push_back((Edge){to, from, 0, 0, 0});
35 m = edges.size();
36 G[from].push_back(m-2);
37 G[to].push_back(m-1);
38 }
39
40 void init() {
41 for(int i = 0; i < m; i++){
42 edges[i].flow = edges[i].flow2;
43 }
44 }
45
46 bool BFS() {
47 memset(vis, 0, sizeof(vis));
48 queue<int> Q;
49 Q.push(t);
50 vis[t] = 1;
51 d[t] = 0;
52 while(!Q.empty()) {
53 int x = Q.front(); Q.pop();
54 for(int i = 0; i < G[x].size(); i++) {
55 Edge& e = edges[G[x][i]^1];
56 if(!vis[e.from] && e.cap > e.flow) {
57 vis[e.from] = 1;
58 d[e.from] = d[x] + 1;
59 Q.push(e.from);
60 }
61 }
62 }
63 return vis[s];
64 }
65
66 void ClearAll(int n) {
67 this->n = n;
68 for(int i = 0; i < n; i++) G[i].clear();
69 edges.clear();
70 }
71
72 int Augment() {
73 int x = t, a = INF;
74 while(x != s) {
75 Edge& e = edges[p[x]];
76 a = min(a, e.cap-e.flow);
77 x = edges[p[x]].from;
78 }
79 x = t;
80 while(x != s) {
81 edges[p[x]].flow += a;
82 edges[p[x]^1].flow -= a;
83 x = edges[p[x]].from;
84 }
85 return a;
86 }
87
88 int MaxFlow(int s, int t, int need) {
89 this->s = s; this->t = t;
90 int flow = 0;
91 BFS();
92 memset(num, 0, sizeof(num));
93 for(int i = 0; i < n; i++) num[d[i]]++;
94 int x = s;
95 memset(cur, 0, sizeof(cur));
96 while(d[s] < n) {
97 if(x == t) {
98 flow += Augment();
99 if(flow >= need) return flow;
100 x = s;
101 }
102 int ok = 0;
103 for(int i = cur[x]; i < G[x].size(); i++) {
104 Edge& e = edges[G[x][i]];
105 if(e.cap > e.flow && d[x] == d[e.to] + 1) { // Advance
106 ok = 1;
107 p[e.to] = G[x][i];
108 cur[x] = i;
109 x = e.to;
110 break;
111 }
112 }
113 if(!ok) {
114 int m = n-1;
115 for(int i = 0; i < G[x].size(); i++) {
116 Edge& e = edges[G[x][i]];
117 if(e.cap > e.flow) m = min(m, d[e.to]);
118 }
119 if(--num[d[x]] == 0) break;
120 num[d[x] = m+1]++;
121 cur[x] = 0;
122 if(x != s) x = edges[p[x]].from;
123 }
124 }
125 return flow;
126 }
127 };
128
129
130 ISAP g;
131
132 double get_dist(Point p1, Point p2) {
133 return sqrt( (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) );
134 }
135
136 int main() {
137 int t;
138 int n; double d;
139 // freopen("a.txt","r",stdin);
140 scanf("%d",&t);
141 while(t--) {
142 scanf("%d %lf",&n, &d);
143 int sum = 0;
144 for(int i = 0; i < n; i++) {
145 scanf("%d %d %d %d",&point[i].x, &point[i].y, &point[i].ni, &point[i].mi);
146 sum += point[i].ni;
147 }
148 //Dinic g;
149 g.ClearAll(maxn);
150 for(int i = 0; i < n; i++) {
151 int left = i + 1; int right = n + left;
152 g.AddEdge(0, left, point[i].ni);
153 g.AddEdge(left, right, point[i].mi);
154 g.AddEdge(right, left, point[i].mi);
155 for(int j = i + 1; j < n; j++) {
156 if( i == j)
157 continue;
158 if(d - get_dist(point[i], point[j]) > 0.00001) {
159 g.AddEdge(right, j + 1, INF);
160 g.AddEdge(j + 1 + n, left, INF);
161 }
162 }
163 }
164 //printf("*%d\n",sum);
165 int c = 0;
166 for(int i = 0; i < n; i++) {
167 int s = 0; int t = i + 1;
168 g.init();
169 if(g.MaxFlow(s, t, INF) == sum)
170 printf(c++ ? " %d" : "%d",i);
171 //printf("%d\n",g.MaxFlow(s, t));
172 }
173 if(c == 0)
174 printf("-1");
175 puts("");
176 }
177 return 0;
178 }

hlg1512March of the Penguins【无向图+拆点】

时间: 2024-08-08 16:08:07

hlg1512March of the Penguins【无向图+拆点】的相关文章

SPOJ 962 Intergalactic Map

Intergalactic Map Time Limit: 6000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: IM64-bit integer IO format: %lld      Java class name: Main Jedi knights, Qui-Gon Jinn and his young apprentice Obi-Wan Kenobi, are entruste

二分图最大匹配,最小路径覆盖,最小点覆盖,最大独立集,最小边覆盖与建图方法

转载请注明出处(别管写的好坏,码字也不容易):http://blog.csdn.net/hitwhacmer1 前言:         有自己写的,有摘的别人的,前面是摘的,也是无心整理,出错是难免的,反正我都不会证明,智人见智,别被我误导了. §1图论点.边集和二分图的相关概念和性质 点覆盖.最小点覆盖 点覆盖集即一个点集,使得所有边至少有一个端点在集合里.或者说是"点" 覆盖了所有"边"..极小点覆盖(minimal vertex covering):本身为点覆

hdu4289 Control --- 最小割,拆点

给一个无向图,告知敌人的起点和终点,你要在图上某些点安排士兵,使得敌人无论从哪条路走都必须经过士兵. 每个点安排士兵的花费不同,求最小花费. 分析: 题意可抽象为,求一些点,使得去掉这些点之后,图分成了两部分,敌人的起点和终点分别在这两部分里.即求最小割. 问题是最小割是边,这里把点拆成两个,自己到自己连边,边权为该点点权.其他题目给的边照连就可以了. 为了方便,对于点i,拆成(i,i+n). 因此,对于题目给的边(a,b),就连双向边边:(a+n,b,inf).(b+n,a,inf) #inc

UVA 12125 - March of the Penguins(最大流)

UVA 12125 - March of the Penguins 题目链接 题意:给定一些冰块,每个冰块上有一些企鹅,每个冰块有一个可以跳出的次数限制,每个冰块位于一个坐标,现在每个企鹅跳跃力为d,问所有企鹅能否跳到一点上,如果可以输出所有落脚冰块,如果没有方案就打印-1 思路:最大流,拆点表示冰块次数限制,然后枚举落脚冰块建图跑最大流即可 代码: #include <cstdio> #include <cstring> #include <queue> #inclu

ZOJ 2182 Cable TV Network(无向图点割-最大流)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2182 题意:给出一个无向图,问最少删掉多少个顶点之后图变得不连通? 思路:将原图每个点拆点(i,i+n),连边<i,i+n,1>,对原图的边(u,v),连边<u+n,v,INF>,<v+n,u,INF>.然后对于每对顶点(i,j)跑最大流(i+n,j).所有最大流的最小值即为答案. struct node { int v,cap,nex

拆点问题

题目详情 n个节点,m条边的无向图,每个节点一个权值w.定义拆除一个节点的代价为与其相邻的节点的权值之和.拆除一个节点后删除所有与该节点相连的边.求拆除所有节点需要花费的最少代价.输入描述:输入包含多组测试数据,每组测试数据第一行先输入n,m(1 ≤ n ≤ 10000; 0 ≤ m ≤ 20000),第二行输入n个整数wi(0 ≤ wi ≤ 105),接下来的m行,每行两个整数u,v代表节点u与v相连(1 ≤ ui, vi ≤ n; ui ≠ vi).输出描述:对于每组测试数据,输出拆除所有节

POJ1966.Cable TV Network——无向图的点连通度

http://poj.org/problem?id=1966 题目描述: 有线电视网络中,中继器的连接是双向的.如果网络中任何两个中继器之间至少有一条路,则中继器网络称为是连通的,否则中继器网络是不连通的.一个空的网络.以及只有一个中继器的网络被认为是连通的.具有n 个中继器的网络的安全系数f 被定义成: (1) f 为n,如果不管删除多少个中继器,剩下的网络仍然是连通的: (2) f 为删除最少的顶点数,使得剩下的网络不连通. 分析: 本题中的安全系数f 实际上就是无向图的顶点连通度κ(G).

Risk UVA - 12264 拆点法+最大流+二分

/** 题目:Risk UVA - 12264 链接:https://vjudge.net/problem/UVA-12264 题意:给n个点的无权无向图(n<=100),每个点有一个非负数ai. 若ai==0则此点归敌方所有,若ai>0则此点归你且上面有ai个属于你的士兵. 保证至少有一个属于你的点与敌方的点相邻.你可以让你的每个士兵最多移动一次 ,每次可以待在原地或者去到相邻的属于你的领地,但每个点至少要留1各士兵, 使得最薄弱的关口尽量坚固.关口是指与敌方点相邻的点,薄弱与坚固分别指兵少

UVA 1660 Cable TV Network 电视网络(无向图,点连通度,最大流)

题意:给一个无向图,求其点连通度?(注意输入问题) 思路: 如果只有1个点,那么输出“1”: 如果有0条边,那么输出“0”: 其他情况:用最大流解决.下面讲如何建图: 图的连通度问题是指:在图中删去部分元素(点或边),使得图中指定的两个点s和t不连通(即不存在从s到t的路径),求至少要删去几个元素. 图的连通度分为点连通度和边连通度: (1)点连通度:只许删点,求至少要删掉几个点(当然,s和t不能删去,这里保证原图中至少有三个点): (2)边连通度:只许删边,求至少要删掉几条边. 并且,有向图和