SGU438 The Glorious Karlutka River =)(最大流)

Posted 新博客↓

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SGU438 The Glorious Karlutka River =)(最大流)相关的知识,希望对你有一定的参考价值。

题目大概说有m个人要过一条宽W的河,人最远跳远距离是d,河上有n个垃圾堆,每个垃圾堆都有坐标和同一时间能容纳的人数,问所有人最少要跳几次才能跳到对岸。

又是一题根据时间拆点的最大流。

二分时间建容量网络判定:按时间对每个垃圾堆拆点,再拆成两点中间连容量为同一时间能容纳的人数的边,所有t时刻的点向所有能到达的t+1时刻的点连边。

另外,可以知道的是如果能到对岸那最坏情况总共需要跳n+m。因为最坏情况每个垃圾堆只能容纳一人,且必须跳完所有垃圾堆才能到达对岸,那么第一个人需要跳m+1次,后面n-1人紧跟着前面那人跳,每跳一次就有新的一个人到达对岸,还需要n-1次,总共就是n+m次。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<algorithm>
  5 using namespace std;
  6 #define INF (1<<30)
  7 #define MAXN 11111
  8 #define MAXM 666666
  9 
 10 struct Edge{
 11     int v,cap,flow,next;
 12 }edge[MAXM];
 13 int vs,vt,NE,NV;
 14 int head[MAXN];
 15 
 16 void addEdge(int u,int v,int cap){
 17     edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0;
 18     edge[NE].next=head[u]; head[u]=NE++;
 19     edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0;
 20     edge[NE].next=head[v]; head[v]=NE++;
 21 }
 22 
 23 int level[MAXN];
 24 int gap[MAXN];
 25 void bfs(){
 26     memset(level,-1,sizeof(level));
 27     memset(gap,0,sizeof(gap));
 28     level[vt]=0;
 29     gap[level[vt]]++;
 30     queue<int> que;
 31     que.push(vt);
 32     while(!que.empty()){
 33         int u=que.front(); que.pop();
 34         for(int i=head[u]; i!=-1; i=edge[i].next){
 35             int v=edge[i].v;
 36             if(level[v]!=-1) continue;
 37             level[v]=level[u]+1;
 38             gap[level[v]]++;
 39             que.push(v);
 40         }
 41     }
 42 }
 43 
 44 int pre[MAXN];
 45 int cur[MAXN];
 46 int ISAP(){
 47     bfs();
 48     memset(pre,-1,sizeof(pre));
 49     memcpy(cur,head,sizeof(head));
 50     int u=pre[vs]=vs,flow=0,aug=INF;
 51     gap[0]=NV;
 52     while(level[vs]<NV){
 53         bool flag=false;
 54         for(int &i=cur[u]; i!=-1; i=edge[i].next){
 55             int v=edge[i].v;
 56             if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){
 57                 flag=true;
 58                 pre[v]=u;
 59                 u=v;
 60                 //aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
 61                 aug=min(aug,edge[i].cap-edge[i].flow);
 62                 if(v==vt){
 63                     flow+=aug;
 64                     for(u=pre[v]; v!=vs; v=u,u=pre[u]){
 65                         edge[cur[u]].flow+=aug;
 66                         edge[cur[u]^1].flow-=aug;
 67                     }
 68                     //aug=-1;
 69                     aug=INF;
 70                 }
 71                 break;
 72             }
 73         }
 74         if(flag) continue;
 75         int minlevel=NV;
 76         for(int i=head[u]; i!=-1; i=edge[i].next){
 77             int v=edge[i].v;
 78             if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
 79                 minlevel=level[v];
 80                 cur[u]=i;
 81             }
 82         }
 83         if(--gap[level[u]]==0) break;
 84         level[u]=minlevel+1;
 85         gap[level[u]]++;
 86         u=pre[u];
 87     }
 88     return flow;
 89 }
 90 int x[55],y[55],c[55];
 91 int n,m,d,w;
 92 bool isok(int time){
 93     vs=n*time*2+1; vt=vs+1; NV=vt+1; NE=0;
 94     memset(head,-1,sizeof(head));
 95     addEdge(vs,n*time*2,m);
 96     for(int i=0; i<n; ++i){
 97         if(y[i]<=d){
 98             for(int t=0; t<time; ++t) addEdge(n*time*2,i*time+t,m);
 99         }
100         if(w-y[i]<=d){
101             for(int t=0; t<time; ++t) addEdge(i*time+t+n*time,vt,m);
102         }
103     }
104     for(int i=0; i<n; ++i){
105         for(int t=0; t<time; ++t) addEdge(i*time+t,i*time+t+n*time,c[i]);
106         for(int t=0; t<time-1; ++t){
107             addEdge(i*time+t+n*time,i*time+t+1,m);
108             for(int j=0; j<n; ++j){
109                 if(i==j || y[i]>y[j]) continue;
110                 if((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])<=d*d) addEdge(i*time+t+n*time,j*time+t+1,m);
111             }
112         }
113     }
114     return ISAP()==m;
115 }
116 int main(){
117     scanf("%d%d%d%d",&n,&m,&d,&w);
118     for(int i=0; i<n; ++i){
119         scanf("%d%d%d",x+i,y+i,c+i);
120     }
121     if(d>=w){
122         putchar(1);
123         return 0;
124     }
125     int l=1,r=n+m+1;
126     while(l<r){
127         int mid=l+r>>1;
128         if(isok(mid)) r=mid;
129         else l=mid+1;
130     }
131     if(l==n+m+1) puts("IMPOSSIBLE");
132     else printf("%d",l+1);
133     return 0;
134 }

 

以上是关于SGU438 The Glorious Karlutka River =)(最大流)的主要内容,如果未能解决你的问题,请参考以下文章

438D - The Child and Sequence

CF438D The Child and Sequence

codeforces438D The Child and Sequence

CF(438D) The Child and Sequence(线段树)

Codeforces 438D The Child and Sequence

CodeForces 438D The Child and Sequence