POJ 3189 二分+Dinic

来源:互联网 发布:html5 棋牌游戏源码 编辑:程序博客网 时间:2024/04/27 21:48

题意:
这里写图片描述
这里写图片描述
思路:
二分跨度 枚举最低座次
建图:源点向每头牛连边权为1的边 每头牛向当前枚举的B的区间这段连上边权为1的边 所有座次向汇点连边权为牛棚容量的边
判判流量是不是等于n

一开始写得是直接枚举答案,在这个答案下枚举座次最低的值 T了。。

(然后我看了一发数据 )
数据中有这样一个点:1000 20 balabala
答案是20

这就很蛋疼了 我枚举了200次 略多 (虽然在我电脑上还是能1s之内跑出来 但是POJ评测机并不快啊)

我就把答案的那个20二分了一下 变成了6

枚举大概几十次 嗯 A了 938ms

//By SiriusRen#include <queue>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define N 1055int n,b,map[N][25],B[25],e=1050,answer;struct Dinic{    int first[N],next[60*N],v[60*N],w[60*N],vis[N],tot;    void add(int x,int y,int z){w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++;}    bool tell(){        memset(vis,-1,sizeof(vis));        queue<int>q;q.push(0);vis[0]=0;        while(!q.empty()){            int t=q.front();q.pop();            for(int i=first[t];~i;i=next[i])                if(w[i]&&vis[v[i]]==-1)                    q.push(v[i]),vis[v[i]]=vis[t]+1;        }        return vis[e]!=-1;    }    int zeng(int x,int y){        if(x==e)return y;        int r=0;        for(int i=first[x];~i&&y>r;i=next[i])            if(vis[v[i]]==vis[x]+1&&w[i]){                int t=zeng(v[i],min(w[i],y-r));                w[i]-=t,w[i^1]+=t,r+=t;            }        if(!r)vis[x]=-1;        return r;    }    int flow(){        int ans=0,jy;        while(tell())while(jy=zeng(0,0x3fffffff))ans+=jy;        return ans;    }    bool solve(int begin,int end){        memset(first,-1,sizeof(first)),tot=0;        for(int i=1;i<=n;i++)            for(int j=begin;j<=end;j++)                add(i,1000+map[i][j],1),add(1000+map[i][j],i,0);        for(int i=1;i<=b;i++)add(1000+i,e,B[i]),add(e,1000+i,0);        for(int i=1;i<=n;i++)add(0,i,1),add(i,0,0);        return flow()==n;    }}dinic;int main(){    scanf("%d%d",&n,&b);    for(int i=1;i<=n;i++)        for(int j=1;j<=b;j++)            scanf("%d",&map[i][j]);    for(int i=1;i<=b;i++)scanf("%d",&B[i]);    int l=0,r=b;    while(l<=r){        int Mid=(l+r)>>1;        for(int i=1;i+Mid<=b;i++)            if(dinic.solve(i,i+Mid)){                answer=Mid,r=Mid-1;                goto ed;            }        l=Mid+1;        ed:;    }    printf("%d\n",answer+1);}

这里写图片描述

0 0