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
");
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
");
160         else printf("Game is NOT VALID
");
161     }
162     return 0;
163 }
原文地址:https://www.cnblogs.com/zyb993963526/p/6686245.html