zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Leetcode Plus One
    Leetcode Swap Nodes in Pairs
    Leetcode Remove Nth Node From End of List
    leetcode Remove Duplicates from Sorted Array
    leetcode Remove Element
    leetcode Container With Most Water
    leetcode String to Integer (atoi)
    leetcode Palindrome Number
    leetcode Roman to Integer
    leetcode ZigZag Conversion
  • 原文地址:https://www.cnblogs.com/WABoss/p/5350455.html
Copyright © 2011-2022 走看看