Pahom on Water
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 885 Accepted Submission(s): 409
Problem Description
Pahom
on Water is an interactive computer game inspired by a short story of
Leo Tolstoy about a poor man who, in his lust for land, forfeits
everything. The game‘s starting screen displays a number of circular
pads painted with colours from the visible light spectrum. More than one
pad may be painted with the same colour (defined by a certain
frequency) except for the two colours red and violet. The display
contains only one red pad (the lowest frequency of 400 THz) and one
violet pad (the highest frequency of 789 THz). A pad may intersect, or
even contain another pad with a different colour but never merely touch
its boundary. The display also shows a figure representing Pahom
standing on the red pad.
The game‘s objective is to walk the figure
of Pahom from the red pad to the violet pad and return back to the red
pad. The walk must observe the following rules:
1.If pad α and pad β
have a common intersection and the frequency of the colour of pad α is
strictly smaller than the frequency of the colour of pad β, then Pahom
figure can walk from α to β during the walk from the red pad to the
violet pad
2. If pad α and pad β have a common intersection and the
frequency of the colour of pad α is strictly greater than the frequency
of the colour of pad β, then Pahom figure can walk from α to β during
the walk from the violet pad to the red pad
3. A coloured pad, with the exception of the red pad, disappears from display when the Pahom figure walks away from it.
The
developer of the game has programmed all the whizzbang features of the
game. All that is left is to ensure that Pahom has a chance to succeed
in each instance of the game (that is, there is at least one valid walk
from the red pad to the violet pad and then back again to the red pad.)
Your task is to write a program to check whether at least one valid path
exists in each instance of the game.
Input
The
input starts with an integer K (1 <= K <= 50) indicating the
number of scenarios on a line by itself. The description for each
scenario starts with an integer N (2 <= N <= 300) indicating the
number of pads, on a line by itself, followed by N lines that describe
the colors, locations and sizes of the N pads. Each line contains the
frequency, followed by the x- and y-coordinates of the pad‘s center and
then the radius. The frequency is given as a real value with no more
than three decimal places. The coordinates and radius are given, in
meters, as integers. All values are separated by a single space. All
integer values are in the range of -10,000 to 10,000 inclusive. In each
scenario, all frequencies are in the range of 400.0 to 789.0 inclusive.
Exactly one pad will have a frequency of “400.0” and exactly one pad
will have a frequency of “789.0”.
Output
The output for each scenario consists of a single line that contains: Game is VALID, or Game is NOT VALID
Sample Input
2
2
400.0 0 0 4
789.0 7 0 2
4
400.0 0 0 4
789.0 7 0 2
500.35 5 0 2
500.32 5 0 3
Sample Output
Game is NOT VALID
Game is VALID
Source
The 2011 South Pacific Programming Contest
题意:平面上有一些点,他们有着各自的坐标,频率,半径 ,可以从一个点到另一个点的条件是两点的距离小于半径之和,现在我们要从频率最小的点走到频率最大的点,规则是每次只能从频率小的走到频率大的,然后又要走回来,规则刚好是相反的,问是否存在这样一种方案使得上述条件成立。
题解:将第二个规则与第一个规则合并,问题就变成了是否存在两条不同的路使得起点(f最低)能够到达终点(f最高)先对所有点按照频率排序,然后构图,频率低的向频率高的连一条容量为1的边,这样的话就能够保证每条边最多走一次,然后求一次最大流,如果最大流大于等于2就存在这样的两条路。
#include <stdio.h> #include <algorithm> #include <queue> #include <string.h> #include <math.h> using namespace std; const int N = 350; const int INF = 999999999; int cap[N][N]; int flow[N]; int pre[N]; int n; struct Node{ int x,y,r; double f; }node[N]; double dis(Node a,Node b){ return sqrt(1.0*((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))); } int bfs(int src,int des){ queue<int> q; for(int i=1;i<=des;i++){ pre[i]=-1; } pre[src]=0; flow[src]=INF; q.push(src); while(!q.empty()){ int u = q.front(); q.pop(); if(u==des) break; for(int i=1;i<=des;i++){ if(i!=src&&cap[u][i]>0&&pre[i]==-1){ pre[i] = u; flow[i] = min(cap[u][i],flow[u]); q.push(i); } } } if(pre[des]==-1) return -1; return flow[des]; } int max_flow(int src,int des){ int ans = 0,increaseRoad; while((increaseRoad=bfs(src,des))!=-1){ int k = des; while(k!=src){ cap[pre[k]][k]-=increaseRoad; cap[k][pre[k]]+=increaseRoad; k = pre[k]; } ans+=increaseRoad; } return ans; } int cmp(Node a,Node b){ return a.f<b.f; } void build(){ scanf("%d",&n); memset(cap,0,sizeof(cap)); for(int i=1;i<=n;i++){ scanf("%lf%d%d%d",&node[i].f,&node[i].x,&node[i].y,&node[i].r); } sort(node+1,node+n+1,cmp); for(int i=1;i<=n;i++){ for(int j=i+1;j<=n;j++){ if(i!=j&&dis(node[i],node[j])<=(node[i].r+node[j].r)){ cap[i][j]=1; } } } } int main(){ int tcase; scanf("%d",&tcase); while(tcase--){ build(); int t = max_flow(1,n); if(t>=2) printf("Game is VALID\n"); else printf("Game is NOT VALID\n"); } }