一个平面上有n个圆, 每个圆都有一个频率, 有两个频率为400和789的圆, 问是否能从频率为400的圆走到频率为789的圆, 并从频率为789的圆走回频率为400的圆, 并且除了频率为400的圆, 其他圆只能走一次。 如果两个圆相交,则去的时候能从频率小的圆走到频率大的圆, 回来的时候能从频率大的圆走到频率小的圆。
思路:
假设起点为s, 终点为t, 其实就是问有没有从s到t的两条不相交路径。
用最大流搞, 把每个点拆为2个, 连一条容量为1的边, 表示只能走一次, 然后求出最大流是不是2就行了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
using namespace std;
#define mxn 800
#define inf 0x3f3f3f3f
struct edge {
int u, v, cap, flow;
edge() {}
edge( int u, int v, int cap, int flow ): u( u ), v( v ), cap( cap ), flow( flow ) {}
};
struct dinic {
int n, m, s, t, cur[mxn], d[mxn];
vector<edge> edges;
vector<int> g[mxn];
void add( int u, int v, int cap ) {
edges.push_back( edge( u, v, cap, 0 ) );
edges.push_back( edge( v, u, 0, 0 ) );
m = edges.size();
g[u].push_back( m - 2 );
g[v].push_back( m - 1 );
}
bool bfs() {
memset( d, -1, sizeof( d ) );
d[s] = 0;
queue<int> q;
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( d[e.v] == -1 && e.cap > e.flow )
d[e.v] = d[x] + 1, q.push( e.v );
}
}
return d[t] != -1;
}
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.v] == d[x] + 1 && ( f = dfs( e.v, min( a, e.cap - e.flow ) ) ) > 0 ) {
flow += f;
e.flow += f;
edges[g[x][i]^1].flow -= f;
a -= f;
if( !a )
break;
}
}
return flow;
}
int mf( int s, int t ) {
this -> s = s, this -> t = t;
int flow = 0;
while( bfs() ) {
memset( cur, 0, sizeof( cur ) );
flow += dfs( s, inf );
}
return flow;
}
}*solver;
struct node {
double x, y, hz, r;
node() {}
void input() {
scanf( "%lf%lf%lf%lf", &hz, &x, &y, &r );
}
}p[mxn];
int n, s, t;
double dis( node a, node b ) {
return sqrt( ( a.x - b.x ) * ( a.x - b.x ) + ( a.y - b.y ) * ( a.y - b.y ) );
}
bool check( int i, int j ) {
if( p[i].hz >= p[j].hz )
return 0;
if( dis( p[i], p[j] ) <= p[i].r + p[j].r )
return 1;
return 0;
}
int main() {
// freopen( "tt.txt", "r", stdin );
int cas;
solver = NULL;
scanf( "%d", &cas );
while( cas-- ) {
if( solver != NULL )
delete solver;
solver = new dinic;
scanf( "%d", &n );
for( int i = 0; i < n; ++i ) {
p[i].input();
if( fabs( p[i].hz - 400 ) < 1e-8 )
s = i;
if( fabs( p[i].hz - 789 ) < 1e-8 )
t = i;
}
for( int i = 0; i < n; ++i ) {
for( int j = i + 1; j < n; ++j ) {
if( check( i, j ) )
solver -> add( ( i << 1 ) | 1, j << 1, 1 );
if( check( j, i ) )
solver -> add( ( j << 1 ) | 1, i << 1, 1 );
}
solver -> add( i << 1, ( i << 1 ) | 1, 1 );
}
solver -> add( s << 1, s << 1 | 1, 1 );
solver -> add( t << 1, t << 1 | 1, 1 );
solver -> add( 775, s << 1, 2 );
solver -> add( ( t << 1 ) | 1, 776, 2 );
int ans = solver -> mf( 775, 776 );
if( ans == 2 )
puts( "Game is VALID" );
else
puts( "Game is NOT VALID" );
}
return 0;
}