hdu 4183 Pahom on Water 最大流

来源:互联网 发布:php mysql select db 编辑:程序博客网 时间:2024/05/29 15:22

一个平面上有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 0x3f3f3f3fstruct 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" );elseputs( "Game is NOT VALID" );}return 0;}


0 0