POJ 2112 网络流加二分

来源:互联网 发布:js页面跳转动画效果 编辑:程序博客网 时间:2024/05/21 10:47
//poj 2112 网络流////学会用二分答案再测是否满流的方法解题//过了//二分思想//为0 的边即不可到的边,除自环,则要化为inf//floyed判inf的优化////题目大意是:K台挤奶机器,C头牛,K不超过30,C不超过200,每台挤奶机器最多可以为M台牛工作,给出这些牛和机器之间,牛和牛之间,//机器与机器之间的距离,在保证让最多的牛都有机器挤奶的情况下,给出其中最长的一头牛移动的距离的最小值。////首先用Floyd求出任意两点之间的最短距离,然后再用二分法限定最多的移动距离d,在求最大流时,搜索增广路的时候同时也判断距离有没有超过d就行了。//分清哪个变量的意义。别弄混,建错图#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<vector>#include<queue>#include<string>#define maxn 300#define inf 0x3f3f3f3f#define INF 0x3f3f3f3fusing namespace std;int s,dest;int c,m,k;int d[maxn][maxn];int w[maxn][maxn];struct Dinic{    int edgeNum,source,sink;    bool vis[maxn];    int d[maxn];    int cur[maxn];    int mark[maxn];    struct edge{        int from,to,cap,flow;    };    vector<edge> edges;    vector<int> mapt[maxn];    void addEdge(int from,int to,int cap){        //pf("%d %d %d\n",from,to,cap);        edges.push_back((edge){from,to,cap,0});        edges.push_back((edge){to,from,0,0});        edgeNum = edges.size();        mapt[from].push_back(edgeNum-2);        mapt[to].push_back(edgeNum-1);    }    bool bfs(){        memset(vis,0,sizeof vis);        queue<int> q;        q.push(source);        d[source] =0; vis[source] =1;        while(!q.empty()){            int x = q.front(); q.pop();            for(int i=0;i<mapt[x].size();i++){                edge& e = edges[mapt[x][i]];                if(!vis[e.to]&&e.cap>e.flow){                    vis[e.to] = 1;                    d[e.to] = d[x] +1;                    q.push(e.to);                }            }        }        return vis[sink];    }    int dfs(int x,int a){        if(x==sink||a==0) return a;        int flow=0,f;        for(int& i=cur[x];i<mapt[x].size();i++){            edge& e = edges[mapt[x][i]];            if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){                e.flow += f;                edges[mapt[x][i]^1].flow -= f;                flow += f;                a -= f;                if(a==0) break;            }        }        return flow;    }    int maxFlow(int source,int sink){        this->sink = sink; this->source = source;        int flow  = 0;        while(bfs()){            memset(cur,0,sizeof cur);            flow += dfs(source,INF);        }        return flow;    }};///floyed里无边的应该化为infvoid floyed(int n){      //  for(int i=1;i<=n;i++)     //   {      ///      for(int j=1;j<=n;j++)      //      cout<<d[i][j]<<" ";     //   cout<<endl;     //   }        for(int t=1;t<=n;t++)        for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++)        {         int temp=d[i][t]+d[t][j];        if(temp<d[i][j])            d[i][j]=temp;        }        //for(int i=1;i<=n;i++)         //   for(int j=1;j<=n;j++)    //        cout<<d[i][j]<<" dis "<<endl;}bool  build(int bound){    Dinic dinic;    for(int i=1;i<=c;i++)    {    dinic.addEdge(s,i,1);   // cout<<s<<" addedge  "<<i<<endl;    }    for(int i=1;i<=c;i++)    for(int j=1;j<=k;j++)    if(w[i][j]<=bound)    {    dinic.addEdge(i,c+j,1);   //cout<<i<<" addedge  "<<c+j<<endl;    }    for(int i=1;i<=k;i++)    {    //cout<<c+i<<" addedge"<<dest<<endl;        dinic.addEdge(c+i,dest,m);    }    int ans=dinic.maxFlow(s,dest);    if(ans==c)        return true;    else        return false;}int main()///k为机器数,c为奶牛数,m为每台机器每天工作的奶牛数的上线{    while(scanf("%d%d%d",&k,&c,&m)!=EOF)    {       int temp=k+c;       for(int i=1;i<=temp;i++)       for(int j=1;j<=temp;j++)       {        scanf("%d",&d[i][j]);        if(d[i][j]==0 && i!=j)            d[i][j]=inf;       }        floyed(temp);        int ma=0;        int mi=inf;       for(int i=k+1;i<=temp;i++)        for(int j=1;j<=k;j++)         {           w[i-k][j]=d[i][j];           if(w[i-k][j]>ma) ma=w[i-k][j];           if(w[i-k][j]<mi) mi=w[i-k][j];          // cout<<i-k<<" "<<j<<" "<<w[i-k][j]<<endl;         }       s=0;       dest=temp+1;       int left=mi;       int right=ma;       int mid;       //cout<<ma<<" "<<mi<<endl;    //   cout<<"miao"<<build(1)<<endl;    int ans;       while(left<=right)       {           mid=(left+right)>>1;          // cout<<mid<<" * "<<build(mid)<<endl;           if(build(mid))           {            ans=mid;            right=mid-1;           }           else            left=mid+1;       }       cout<<ans<<endl;    }}//2 3 2//0 3 2 1 1//3 0 3 2 0//2 3 0 1 0//1 2 1 0 2//1 0 0 2 0

0 0
原创粉丝点击