HDU 4183

给出一个有向图,以及src和dst。判断是否存在从src到dst的两条路径,使得除了src和dst外,没有其它点同时属于两条路径。

给每个点一个为1的点容量(src和dst为2),边的容量也是1,然后判断最大流是否大于等于2.

收获:

边不能重复:将点拆成两个点考虑,然后考虑匹配。

点不能重复:给每个点一个点容量(其实还是拆点),然后考虑流。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 #include <vector>
  5 #define maxn 620
  6 #define oo 0x3f3f3f3f
  7 #define eps 1e-10
  8 using namespace std;
  9
 10 int sg( double x ) {
 11     return (x>-eps)-(x<eps);
 12 }
 13 struct Edge {
 14     int u, v, f;
 15     Edge( int u, int v, int f ):u(u),v(v),f(f){}
 16 };
 17 struct Dinic {
 18     int n, src, dst;
 19     vector<Edge> edge;
 20     vector<int> g[maxn];
 21     int dep[maxn], cur[maxn];
 22
 23     void init( int n, int src, int dst ) {
 24         this->n = n;
 25         this->src = src;
 26         this->dst = dst;
 27         for( int u=1; u<=n; u++ )
 28             g[u].clear();
 29         edge.clear();
 30     }
 31     void add_edge( int u, int v, int f ) {
 32         g[u].push_back( edge.size() );
 33         edge.push_back( Edge(u,v,f) );
 34         g[v].push_back( edge.size() );
 35         edge.push_back( Edge(v,u,0) );
 36     }
 37     bool bfs() {
 38         queue<int> qu;
 39         memset( dep, 0, sizeof(dep) );
 40         qu.push( src );
 41         dep[src] = 1;
 42         while( !qu.empty() ) {
 43             int u=qu.front();
 44             qu.pop();
 45             for( int t=0; t<g[u].size(); t++ ) {
 46                 Edge &e = edge[g[u][t]];
 47                 if( e.f && !dep[e.v] ) {
 48                     dep[e.v] = dep[e.u]+1;
 49                     qu.push( e.v );
 50                 }
 51             }
 52         }
 53         return dep[dst];
 54     }
 55     int dfs( int u, int a ) {
 56         if( u==dst || a==0 ) return a;
 57         int remain=a, past=0, na;
 58         for( int &t=cur[u]; t<g[u].size(); t++ ) {
 59             Edge &e=edge[g[u][t]];
 60             Edge &ve=edge[g[u][t]^1];
 61             if( dep[e.v]==dep[e.u]+1 && e.f && (na=dfs(e.v,min(e.f,remain))) ) {
 62                 remain -= na;
 63                 past += na;
 64                 e.f -= na;
 65                 ve.f += na;
 66                 if( remain==0 ) break;
 67             }
 68         }
 69         return past;
 70     }
 71     int maxflow() {
 72         int flow = 0;
 73         while( bfs() ) {
 74             memset( cur, 0, sizeof(cur) );
 75             flow += dfs(src,oo);
 76         }
 77         return flow;
 78     }
 79 };
 80
 81 int n;
 82 double freq[maxn];
 83 int xx[maxn], yy[maxn], rr[maxn];
 84 vector<int> g[maxn];
 85 Dinic D;
 86
 87 bool cross( int i, int j ) {
 88     int dx = xx[i]-xx[j];
 89     int dy = yy[i]-yy[j];
 90     int sr = rr[i]+rr[j];
 91     return dx*dx+dy*dy <= sr*sr;
 92 }
 93 int main() {
 94     int T;
 95     scanf( "%d", &T );
 96     while( T-- ) {
 97         scanf( "%d", &n );
 98         int src, dst;
 99         for( int i=1; i<=n; i++ ) {
100             scanf( "%lf%d%d%d", freq+i, xx+i, yy+i, rr+i );
101             if( sg(freq[i]-789.0)==0 ) dst=i;
102             if( sg(freq[i]-400.0)==0 ) src=i;
103         }
104         for( int i=1; i<=n; i++ ) {
105             g[i].clear();
106             for( int j=1; j<=n; j++ )
107                 if( cross(i,j) && sg(freq[i]-freq[j])<0 ) {
108                     g[i].push_back( j );
109                 }
110         }
111         D.init( n+n, src, dst );
112         for( int u=1; u<=n; u++ ) {
113             D.add_edge( u, u+n, 1+(u==src) );
114             for( int t=0; t<g[u].size(); t++ ) {
115                 int v=g[u][t];
116                 if( u==src && v==dst )
117                     D.add_edge( u+n, v, oo );
118                 else
119                     D.add_edge( u+n, v, 1 );
120             }
121         }
122         int flow = D.maxflow();
123         bool ok = flow>=2;
124         printf( "Game is %s\n", ok ? "VALID" : "NOT VALID" );
125     }
126 }

时间: 2024-10-24 17:26:06

HDU 4183的相关文章

HDU 4183 Pahom on Water 来回走不重复点的网络流

题目来源:HDU 4183 Pahom on Water 题意:若干个区域 每个区域有一个值 区域是圆 给出圆心和半径 从起点(值为400.0)到终点(值为789.0)满足走相交的圆 并且值必须递增 然后从终点到起点 值必须递减 此外区域只能去一次 思路:建图 相互能走的区域连一条边 因为只能走一次 所以拆点 如果没有来回 只有去 那么判断最大流为1即可 现在还要回来 并且回来的条件和去的条件想法(一个递增一个递减)可以反向考虑给源点cap=2 最大流为2 #include <cstdio>

HDU 4183 Pahom on Water(最大流)

https://vjudge.net/problem/HDU-4183 题意: 这道题目的英文实在是很难理解啊. 给出n个圆,每个圆有频率,x.y轴和半径r4个属性,每次将频率为400的圆作为起点,频率为789点作为终点.从源点到汇点时必须从频率小的到频率大的,而从汇点到源点时必须从频率大的到频率小的.前提时这两个圆必须严格相交.每个点只能走一次.判断是否能从起点出发到达终点,并再次返回起点. 思路: 其实就是判断最大流是否大于等于2.因为每个点只能走一次,用拆点法. 1 #include<io

HDU 4183 Pahom on Water(最大流SAP)

Pahom on Water Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 629    Accepted Submission(s): 288 Problem Description Pahom on Water is an interactive computer game inspired by a short story of

hdu 4183(网络流)

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

【网络流】 HDU 4183 Pahom on Water 拆点

题意:求两条路 能从 400.0 -> 789.0 且这两条路不想交(除了端点400,789 ) 求只能走一次的网络流需要用到拆点, 将点i  拆成 i 和 i+n  i->i+n的容量为经过的次数  (这题为1 ) 若i 能到达 j  则连接 i+n-> j #include <cstdio> #include <cstring> #include <cstdlib> #include <string> #include <iost

hdu 4183 EK最大流算法

欢迎参加——每周六晚的BestCoder(有米!) Pahom on Water Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 678    Accepted Submission(s): 312 Problem Description Pahom on Water is an interactive computer game ins

HDU 4183Pahom on Water(网络流之最大流)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4183 这题题目意思很难看懂..我看了好长时间也没看懂..最终是从网上找的翻译..我就在这翻译一下吧. 意思大约是:有多个点,每个点给出坐标与半径,加入两个点相交,就可以从这两个点走.题目要求先从起点到终点,再从终点回到起点.从起点到终点的过程中,只能从频率小的走到频率大的点(前提是两点相交),从终点到起点的过程中,只能从频率大的走到频率小的.在走的过程中,除了起点与终点,别的只要走过就会消失,就是说

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include