poj 2112(二分搜索+最短路+最大流)

#include <stdio.h>
#include <iostream>
#include <string.h>
#define VM 100010
#define EM 400010

using namespace std;
const long long inf = 1<<30;

struct E
{
    long long to, frm, nxt, cap;
}edge[EM];

long long head[VM], e;//建图时初始化
long long dep[VM], gap[VM];//ISAP函数内初始化

void init()
{
 e = 0;
 memset(head, -1, sizeof(head));
}

void addEdge(long long cu, long long cv, long long cw)
{
    edge[e].frm = cu;
    edge[e].to = cv;
    edge[e].cap = cw;
    edge[e].nxt = head[cu];
    head[cu] = e++;

    edge[e].frm = cv;
    edge[e].to = cu;
    edge[e].cap = 0;
    edge[e].nxt = head[cv];
    head[cv] = e++;
}

long long que[VM];

void BFS(long long des)
{
    memset(dep, -1, sizeof(dep));
    memset(gap, 0, sizeof(gap));
    gap[0] = 1;
    long long front = 0, rear = 0;
    dep[des] = 0;
    que[rear++] = des;
    long long u, v;
    while (front != rear)
    {
        u = que[front++];
        front = front%VM;
        for (long long i=head[u]; i!=-1; i=edge[i].nxt)
        {
            v = edge[i].to;
            if (edge[i].cap != 0 || dep[v] != -1)
                continue;
            que[rear++] = v;
            rear = rear % VM;
            ++gap[dep[v] = dep[u] + 1];
        }
    }
}

long long cur[VM], stack[VM];
//sap模板
long long ISAP(long long src, long long des, long long n)//源点、汇点、图中点的总数      
{
    long long res = 0;
    BFS(des);
    long long top = 0;
    memcpy(cur, head, sizeof(head));
    long long u = src, i;
    while (dep[src] < n)
    {
        if (u == des)
        {
            long long temp = inf, inser = n;
            for (i=0; i!=top; ++i)
                if (temp > edge[stack[i]].cap)
                {
                    temp = edge[stack[i]].cap;
                    inser = i;
                }
            for (i=0; i!=top; ++i)
            {
                edge[stack[i]].cap -= temp;
                edge[stack[i]^1].cap += temp;
            }
            res += temp;
            top = inser;
            u = edge[stack[top]].frm;
        }

        if (u != des && gap[dep[u] -1] == 0)
            break;
        for (i = cur[u]; i != -1; i = edge[i].nxt)
            if (edge[i].cap != 0 && dep[u] == dep[edge[i].to] + 1)
                break;

        if (i != -1)
        {
            cur[u] = i;
            stack[top++] = i;
            u = edge[i].to;
        }
        else
        {
            long long min = n;
            for (i = head[u]; i != -1; i = edge[i].nxt)
            {
                if (edge[i].cap == 0)
                    continue;
                if (min > dep[edge[i].to])
                {
                    min = dep[edge[i].to];
                    cur[u] = i;
                }
            }
            --gap[dep[u]];
            ++gap[dep[u] = min + 1];
            if (u != src)
                u = edge[stack[--top]].frm;
        }
    }
    return res;
}

int main()
{
 long long i,j,K,C,m,n,c,k,MAX;
 long long g[235][235]; 
 while(scanf("%lld %lld %lld",&K,&C,&m) != EOF)
 {
  n = K + C;
  for(i = 1; i <= n; i++)
  { 
   for(j = 1; j <= n; j++)
   {
    scanf("%lld",&g[i][j]);
    if (g[i][j] == 0 && i != j)
     g[i][j] = inf;
   }
  }
  for(i=1;i<=n;i++)
  {
   for(j=1;j<=n;j++)
    for(k=1;k<=n;k++)
     g[j][k]=min(g[j][i]+g[i][k],g[j][k]);
  }
  MAX = 0;
  for(i=1;i<=K+C;i++)
  { 
   for(j=1;j<=K+C;j++)
   {
    if(MAX<g[i][j])
     MAX = g[i][j];
   }
  }
  long long l=0,r=MAX,mid;
  long long ans;
  while(l <= r)
  {
   mid = (l + r)>>1;
   init();
   for( i = 1; i <= K; i++)
   {
    addEdge(1,1+i,m);
   }
   for( i =K + 1; i <= n; i++)
   {
    addEdge(1 + i, n + 2, 1);
   }
   for(i = 1; i <= K; i++)
   { 
    for(j = K + 1; j <= n; j++)
    {
     if(g[i][j] <= mid)
      addEdge(1 + i, 1 + j, 1);
    }
   }
   if(ISAP(1,n+2,n+2) == C)
   {
    ans = mid;
    r = mid - 1;
   }
   else
    l = mid + 1;
  }
  printf("%lld\n",ans);

 }
}

 

你可能感兴趣的:(二分搜索,include,最大流)