HDU 4183 Pahom on Water(最大流)
https://vjudge.net/problem/HDU-4183
题意:
这道题目的英文实在是很难理解啊。
给出n个圆,每个圆有频率,x、y轴和半径r4个属性,每次将频率为400的圆作为起点,频率为789点作为终点。从源点到汇点时必须从频率小的到频率大的,而从汇点到源点时必须从频率大的到频率小的。前提时这两个圆必须严格相交。每个点只能走一次。判断是否能从起点出发到达终点,并再次返回起点。
思路:
其实就是判断最大流是否大于等于2。因为每个点只能走一次,用拆点法。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 8 const int maxn=1000+5; 9 const int INF=0x3f3f3f3f; 10 11 struct Point 12 { 13 double p; 14 int x,y,r; 15 }point[maxn],s,t; 16 17 bool cacl(Point a,Point b) 18 { 19 double l1=(b.y-a.y)*(b.y-a.y)+(b.x-a.x)*(b.x-a.x); 20 double l2=(double)(a.r+b.r)*(a.r+b.r); 21 if(l1<l2) return true; 22 else return false; 23 } 24 25 struct Edge 26 { 27 int from,to,cap,flow; 28 Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){} 29 }; 30 31 struct Dinic 32 { 33 int n,m,s,t; 34 vector<Edge> edges; 35 vector<int> G[maxn]; 36 bool vis[maxn]; 37 int cur[maxn]; 38 int d[maxn]; 39 40 void init(int n) 41 { 42 this->n=n; 43 for(int i=0;i<n;++i) G[i].clear(); 44 edges.clear(); 45 } 46 47 void AddEdge(int from,int to,int cap) 48 { 49 edges.push_back( Edge(from,to,cap,0) ); 50 edges.push_back( Edge(to,from,0,0) ); 51 m=edges.size(); 52 G[from].push_back(m-2); 53 G[to].push_back(m-1); 54 } 55 56 bool BFS() 57 { 58 queue<int> Q; 59 memset(vis,0,sizeof(vis)); 60 vis[s]=true; 61 d[s]=0; 62 Q.push(s); 63 while(!Q.empty()) 64 { 65 int x=Q.front(); Q.pop(); 66 for(int i=0;i<G[x].size();++i) 67 { 68 Edge& e=edges[G[x][i]]; 69 if(!vis[e.to] && e.cap>e.flow) 70 { 71 vis[e.to]=true; 72 d[e.to]=d[x]+1; 73 Q.push(e.to); 74 } 75 } 76 } 77 return vis[t]; 78 } 79 80 int DFS(int x,int a) 81 { 82 if(x==t || a==0) return a; 83 int flow=0, f; 84 for(int &i=cur[x];i<G[x].size();++i) 85 { 86 Edge &e=edges[G[x][i]]; 87 if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0) 88 { 89 e.flow +=f; 90 edges[G[x][i]^1].flow -=f; 91 flow +=f; 92 a -=f; 93 if(a==0) break; 94 } 95 } 96 return flow; 97 } 98 99 int Maxflow(int s,int t) 100 { 101 this->s=s; this->t=t; 102 int flow=0; 103 while(BFS()) 104 { 105 memset(cur,0,sizeof(cur)); 106 flow +=DFS(s,INF); 107 } 108 return flow; 109 } 110 }DC; 111 112 int n; 113 114 int main() 115 { 116 //freopen("D:\\input.txt","r",stdin); 117 int T; 118 scanf("%d",&T); 119 while(T--) 120 { 121 scanf("%d",&n); 122 DC.init(2*n+10); 123 for(int i=1;i<=n;i++) 124 { 125 scanf("%lf%d%d%d",&point[i].p,&point[i].x,&point[i].y,&point[i].r); 126 if(point[i].p==400) 127 { 128 s=point[i]; 129 i--; 130 n--; 131 } 132 else if(point[i].p==789) 133 { 134 t=point[i]; 135 i--; 136 n--; 137 } 138 } 139 140 if(cacl(s,t)) 141 { 142 printf("Game is VALID\n"); 143 continue; 144 } 145 146 for(int i=1;i<=n;i++) 147 { 148 DC.AddEdge(i,n+i,1); //拆点 149 if(cacl(s,point[i]) && s.p<point[i].p) DC.AddEdge(0,i,1); 150 if(cacl(point[i],t) && point[i].p<t.p) DC.AddEdge(n+i,2*n+1,1); 151 for(int j=1;j<=n;j++) 152 { 153 if(i==j) continue; 154 if(cacl(point[i],point[j]) && point[i].p<point[j].p) 155 DC.AddEdge(n+i,j,1); 156 } 157 } 158 int ans=DC.Maxflow(0,2*n+1); 159 if(ans>=2) printf("Game is VALID\n"); 160 else printf("Game is NOT VALID\n"); 161 } 162 return 0; 163 }