poj 3498(最大流+拆点)

题目链接:http://poj.org/problem?id=3498

思路:首先设一个超级源点,将源点与各地相连,边容量为各点目前的企鹅数量,然后就是对每个冰块i进行拆点了(i,i+n),边容量为能够接受的受损程度,这样就把点权问题转化为边权问题了,然后就是对于那些能够相互跳跃的冰块之间连边(i+n,j),(j+n,i),边容量为inf。最后就是枚举汇点看是否等于总数。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<cmath>
  7 using namespace std;
  8 #define MAXN 222
  9 #define MAXM 2222222
 10 #define inf 1<<30
 11 
 12 struct Edge{
 13     int v,cap,next;
 14 }edge[MAXM];
 15 
 16 int n,NE,vs,vt,NV;
 17 double dist;
 18 int head[MAXN];
 19 
 20 void Insert(int u,int v,int cap)
 21 {
 22     edge[NE].v=v;
 23     edge[NE].cap=cap;
 24     edge[NE].next=head[u];
 25     head[u]=NE++;
 26 
 27     edge[NE].v=u;
 28     edge[NE].cap=0;
 29     edge[NE].next=head[v];
 30     head[v]=NE++;
 31 }
 32 
 33 int level[MAXN],gap[MAXN];
 34 void bfs(int vt)
 35 {
 36     memset(level,-1,sizeof(level));
 37     memset(gap,0,sizeof(gap));
 38     level[vt]=0;
 39     gap[level[vt]]++;
 40     queue<int>que;
 41     que.push(vt);
 42     while(!que.empty()){
 43         int u=que.front();
 44         que.pop();
 45         for(int i=head[u];i!=-1;i=edge[i].next){
 46             int v=edge[i].v;
 47             if(level[v]!=-1)continue;
 48             level[v]=level[u]+1;
 49             gap[level[v]]++;
 50             que.push(v);
 51         }
 52     }
 53 }
 54 
 55 int pre[MAXN],cur[MAXN];
 56 int SAP(int vs,int vt)
 57 {
 58     bfs(vt);
 59     memset(pre,-1,sizeof(pre));
 60     memcpy(cur,head,sizeof(cur));
 61     int maxflow=0,aug=inf;
 62     int u=pre[vs]=vs;
 63     gap[0]=NV;
 64     while(level[vs]<NV){
 65         bool flag=false;
 66         for(int &i=cur[u];i!=-1;i=edge[i].next){
 67             int v=edge[i].v;
 68             if(edge[i].cap>0&&level[u]==level[v]+1){
 69                 flag=true;
 70                 pre[v]=u;
 71                 u=v;
 72                 aug=min(aug,edge[i].cap);
 73                 if(v==vt){
 74                     maxflow+=aug;
 75                     for(u=pre[v];v!=vs;v=u,u=pre[u]){
 76                         edge[cur[u]].cap-=aug;
 77                         edge[cur[u]^1].cap+=aug;
 78                     }
 79                     aug=inf;
 80                 }
 81                 break;
 82             }
 83         }
 84         if(flag)continue;
 85         int minlevel=NV;
 86         for(int i=head[u];i!=-1;i=edge[i].next){
 87             int v=edge[i].v;
 88             if(edge[i].cap>0&&level[v]<minlevel){
 89                 minlevel=level[v];
 90                 cur[u]=i;
 91             }
 92         }
 93         if(--gap[level[u]]==0)break;
 94         level[u]=minlevel+1;
 95         gap[level[u]]++;
 96         u=pre[u];
 97     }
 98     return maxflow;
 99 }
100 struct Point{
101     double x,y;
102     int num1,num2;
103 }p[MAXN];
104 
105 double Get_dist(int i,int j)
106 {
107     double d1=(p[i].x-p[j].x)*(p[i].x-p[j].x);
108     double d2=(p[i].y-p[j].y)*(p[i].y-p[j].y);
109     return sqrt(d1+d2);
110 }
111 void Build()
112 {
113     NE=0;
114     memset(head,-1,sizeof(head));
115     vs=0,NV=2*n+1;
116     for(int i=1;i<=n;i++)Insert(vs,i,p[i].num1);
117     for(int i=1;i<=n;i++)Insert(i,i+n,p[i].num2);
118     for(int i=1;i<=n;i++){
119         for(int j=i+1;j<=n;j++){
120             if(Get_dist(i,j)<=dist){
121                 Insert(i+n,j,inf);
122                 Insert(j+n,i,inf);
123             }
124         }
125     }
126 }
127 int ans[MAXN],cnt;
128 int main()
129 {
130     int _case,sum;
131     scanf("%d",&_case);
132     while(_case--){
133         scanf("%d%lf",&n,&dist);
134         sum=0;
135         for(int i=1;i<=n;i++){
136             scanf("%lf%lf%d%d",&p[i].x,&p[i].y,&p[i].num1,&p[i].num2);
137             sum+=p[i].num1;
138         }
139         cnt=0;
140         for(int i=1;i<=n;i++){
141             Build();
142             if(SAP(vs,i)==sum)ans[cnt++]=i;
143         }
144         if(cnt){
145             for(int i=0;i<cnt;i++){
146                 printf(i?" %d":"%d",ans[i]-1);
147             }
148             printf("
");
149         }else
150             puts("-1");
151     }
152     return 0;
153 }
View Code
原文地址:https://www.cnblogs.com/wally/p/3283660.html