HDU4183 Pahom on Water(来回走最大流,一个点只经过一次)

 2023-09-28 阅读 15 评论 0

摘要:题意: 有n个圆,每个圆的中心和半径和一个频率都给定,只有一个频率最高的789为紫色,只有一个最低的400为红色,规则如下: 1.当两个圆严格相交时,且人是从红色到紫色的方向运动时可以由低频率向高频率移动 2.当两个圆严格相交

题意:

有n个圆,每个圆的中心和半径和一个频率都给定,只有一个频率最高的789为紫色,只有一个最低的400为红色,规则如下:

1.当两个圆严格相交时,且人是从红色到紫色的方向运动时可以由低频率向高频率移动

2.当两个圆严格相交时,且人是从紫色到红色的方向运动时可以由高频率向低频率运动

3.除了红色的圆以外,离开某个圆之后就会消失(即只能走一次)

思路:

如果一开始红色和紫色就相交,则存在合理方案。否则

本题要求是先从红点出发,经过紫点之后再返回红点,如果以红点作为源点,网络流算法不能先到达一个T,然后再到达另一个T,

所以不妨以紫点作为源点sp,红点作为tp,将点拆分成i和i+n,然后建边(i, i+n, 1), (sp, sp+n, 2)如果两个圆严格相交,设i的频率

大于j的频率,则(i+n, j, 1)反之(j+n, i, 1),求出最大流为2则存在合理方案。把S(紫色) -> T(红色)的两个流中的一个流反向,就可以形成一个

T -> S -> T的方案。

#include <bits/stdc++.h>
using namespace std;const int maxn = 300 + 5;
const int inf = 0x3f3f3f3f;
struct point{double f;double x, y, r;
} p[maxn];
struct edge{int to, w, next;
} ed[maxn*maxn<<2];
int k, n, sp, tp;
int head[maxn<<1], tot, d[maxn<<1], maxflow;
inline void init(){memset( head, -1, sizeof(head) );tot = 1;
}inline double getlen2( const point a, const point b ){double x1 = a.x, x2 = b.x;double y1 = a.y, y2 = b.y;return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}inline bool judge(point a, point b){return getlen2(a, b) < (a.r+b.r)*(a.r+b.r);
}inline void add( int u, int v, int w ){ed[++tot].to = v; ed[tot].w = w; ed[tot].next = head[u]; head[u] = tot;ed[++tot].to = u; ed[tot].w = 0; ed[tot].next = head[v]; head[v] = tot;
}inline bool bfs(){memset( d, 0, sizeof(d) );queue<int> q;d[sp] = 1;q.push(sp);while( !q.empty() ){int x = q.front();q.pop();for( int i=head[x]; i!=-1; i=ed[i].next ){int y = ed[i].to;if( ed[i].w && !d[y] ){d[y] = d[x] + 1;q.push(y);if( y==tp ) return 1;}}}return 0;
}inline int dfs( int x, int flow ){if( x==tp ) return flow;int res = flow, k;for( int i=head[x]; i!=-1&&res; i=ed[i].next ){int y = ed[i].to;if( ed[i].w && d[y]==d[x]+1 ){k = dfs( y, min( res, ed[i].w ) );if(!k) d[y] = 0;ed[i].w -= k;ed[i^1].w += k;res -= k;}}return flow - res;
}inline void dinic(){int flow = maxflow = 0;while( bfs() ){while( flow = dfs(sp, inf) ) maxflow += flow;}
}int main(){// freopen("in.txt", "r", stdin);scanf("%d", &k);while( k-- ){scanf("%d", &n);init();for( int i=1; i<=n; i++ ){scanf("%lf%lf%lf%lf", &p[i].f, &p[i].x, &p[i].y, &p[i].r);if( p[i].f==400.0 ) tp = i;else if( p[i].f==789.0 ) sp = i;else add( i, i+n, 1 );}if( judge( p[sp], p[tp] ) ){puts("Game is VALID");continue;}add( sp, sp+n, 2 );for( int i=1; i<=n; i++ )for( int j=i+1; j<=n; j++ ){if( judge(p[i], p[j]) ){if( p[i].f<p[j].f ) add( j+n, i, 1 );else add( i+n, j, 1 );}}dinic();// cout << maxflow << endl;if( maxflow>=2 ) puts("Game is VALID");else puts("Game is NOT VALID");}return 0;
}
/*
Game is NOT VALID
Game is VALID*/

 

转载于:https://www.cnblogs.com/WAautomaton/p/11143483.html

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/2/102035.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息