POJ2112 Optimal Milking

二分+最大流

#include <iostream>
#include <string.h>
using namespace std;
const int MAXN = 250;
const int MAXE = MAXN*MAXN;
struct node
{
       int v, w, next;       
}mapp[MAXE];
int id;
int head[MAXN];
void init()
{
     id = 0;
     memset(head, -1, sizeof(head));     
}
void addedge(int u, int v, int val)
{
     mapp[id].v = v, mapp[id].w = val, mapp[id].next = head[u], head[u] = id ++;
     
     mapp[id].v = u, mapp[id].w = 0, mapp[id].next = head[v], head[v] = id ++;
}
const int inf = 1<<28;
int cur[MAXE], dist[MAXN], pre[MAXN], gap[MAXN];
int SAP(int s, int e, int n)
{
    memcpy(cur, head, sizeof(head));
    memset(dist, 0, sizeof(dist));
    memset(gap, 0, sizeof(gap));
    int u, v;
    int flow = 0;
    int bottle = inf;
    gap[s] = n;
    u = pre[s] = s;
    bool flag = true;
    while (dist[s] < n){
          flag = false;
          for (int &j = cur[u]; j != -1; j = mapp[j].next){
              v = mapp[j].v;
              if (mapp[j].w > 0 && dist[v]+1 == dist[u]){
                 flag = true;
                 if (mapp[j].w < bottle){
                    bottle = mapp[j].w;              
                 }
                 pre[v] = u;
                 u = v;
                 if (u == e){
                    flow += bottle;
                    while (u != s){
                          u = pre[u];
                          mapp[cur[u]].w -= bottle;
                          mapp[cur[u]^1].w += bottle;
                    }
                    bottle = inf;      
                 }        
                 break; 
              }         
          }
          if (flag) continue;
          int mindis = n;
          for (int j = head[u]; j != -1; j = mapp[j].next){
              v = mapp[j].v;
              if (mapp[j].w > 0 && mindis > dist[v]){
                 mindis = dist[v], cur[u] = j;              
              }    
          } 
          if (!(--gap[dist[u]])){
             break;                       
          }
          gap[dist[u] = mindis+1] ++;
          u = pre[u];
    }
    return flow;
}
void pri(int n)
{
     for (int i = 1; i <= n; i ++){
         cout<<"i:"<<i<<endl;
         for (int j = head[i]; j != -1; j = mapp[j].next){
             cout<<mapp[j].v<<' '<<mapp[j].w <<endl;    
         }    
     }    
}
int maze[MAXN][MAXN];
int dis[MAXN][MAXN];
int Que[10*MAXE];
bool inque[MAXN];
void SPFA(int s, int n, int k)
{
     for (int i = 1; i <= n; i ++){
         dis[k][i] = inf, inque[i] = false;
         if (s == 1){  
            for (int j = 1; j <= n; j ++){
                if (!maze[i][j])maze[i][j] = inf;    
            }  
         }
     }
     dis[k][s] = 0;
     int rear, front;
     rear = front = 0;
     Que[rear ++] = s;
     inque[s] = true;
     while (front < rear){
         int pre = Que[front ++];
         inque[pre] = false;
         for (int i = 1; i <= n; i ++){
             if (dis[k][i] > dis[k][pre] + maze[pre][i]){
                dis[k][i] = dis[k][pre] + maze[pre][i];
                if (!inque[i]){
                   inque[i] = true;               
                   Que[rear ++] = i;
                }
                            
             }    
         }
     }
}
int k, c, m;
int s, t;
int ans;

void binary(int low, int high, int n)
{
     while (low < high){
           int mid = (low + high) >> 1;
           init();
           for (int i = 1; i <= k; i ++){
               addedge(s, i, m);
               for (int j = k+1; j <= c+k; j ++){
                   if (i == 1)addedge(j, t, 1);
                   if (dis[i][j] <= mid){
                      addedge(i, j, 1); 
                   }    
               }    
           }  
           int cmp = SAP(s, t, n);
           if (cmp == c){
              ans = mid;
              high = mid;           
           }    
           else low = mid+1;
     }
}
int main()
{
    
    while (scanf("%d%d%d", &k, &c, &m) != EOF){
          int n = k+c;
          for (int i = 1; i <= n; i ++){
              for (int j = 1; j <= n; j ++){
                  scanf("%d", &maze[i][j]);    
              }    
          }      
          int high = -1, low = INT_MAX;
          for (int i = 1; i <= k; i ++){
              SPFA(i, n, i);
              
              for (int j = k+1; j <= n; j ++){
                  //cout<<dis[i][j]<<' ';
                  if (high < dis[i][j] && dis[i][j] != inf)high = dis[i][j];
                  if (low > dis[i][j] && dis[i][j] != inf)low = dis[i][j];    
              }
              //cout<<endl;
          }
          s = n+1, t = n+2;
          //cout<<high<<' '<<low<<endl;
          ans = -1;
          binary(low, high+1, n);
          printf("%d\n", ans);
    }
    return 0;    
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值