POJ 2112 Optimal Milking(二分+floyd+最大流)

来源:互联网 发布:地方门户 php 编辑:程序博客网 时间:2024/04/29 05:19

POJ 2112 Optimal Milking(二分+floyd+最大流)

http://poj.org/problem?id=2112

题意:

k个机器,每个机器最多服务m头牛。

c头牛,每个牛需要1台机器来服务。

告诉你牛与机器(牛与牛,机器与机器)每个之间的直接距离。

问:让所有的牛都被服务的情况下,使走的最远的牛的距离最短,求这个距离。

分析:

       首先用floyd算法求出任意两点(牛或机器)之间的最短距离.

       然后我们二分该距离,建立网络流图.假设我们当前二分的距离为x.

       首先是源点s到任意牛i之间有边(s,i,1).   

       然后是任意机器j到汇点t之间有边(j,t,m).

       然后对于任意牛i和机器j,如果他们之间的距离<=x,那么就添加一条(i,j,1)的边.

       最终我们求最大流,看看最大流是否等于牛的数目C即可.

AC代码:

#include<cstdio>#include<cstring>#include<queue>#include<vector>#include<algorithm>#define INF 1e9using namespace std;const int maxn=300+10;struct Edge{    int from,to,cap,flow;    Edge(){}    Edge(int f,int t,int c,int fl):from(f),to(t),cap(c),flow(fl){}};struct Dinic{    int n,m,s,t;    vector<Edge> edges;    vector<int> G[maxn];    int d[maxn];    int cur[maxn];    bool vis[maxn];    void init(int n,int s,int t)    {        this->n=n, this->s=s, this->t=t;        edges.clear();        for(int i=0;i<n;i++) G[i].clear();    }    void AddEdge(int from,int to,int cap)    {        edges.push_back( Edge(from,to,cap,0) );        edges.push_back( Edge(to,from,0,0) );        m = edges.size();        G[from].push_back(m-2);        G[to].push_back(m-1);    }    bool BFS()    {        queue<int> Q;        memset(vis,0,sizeof(vis));        d[s]=0;        vis[s]=true;        Q.push(s);        while(!Q.empty())        {            int x=Q.front(); Q.pop();            for(int i=0;i<G[x].size();i++)            {                Edge& e=edges[G[x][i]];                if(!vis[e.to] && e.cap>e.flow)                {                    vis[e.to]=true;                    Q.push(e.to);                    d[e.to]=d[x]+1;                }            }        }        return vis[t];    }    int DFS(int x,int a)    {        if(x==t || a==0) return a;        int flow=0,f;        for(int& i=cur[x];i<G[x].size();++i)        {            Edge& e=edges[G[x][i]];            if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0)            {                e.flow+=f;                edges[G[x][i]^1].flow-=f;                flow+=f;                a-=f;                if(a==0) break;            }        }        return flow;    }    int max_flow()    {        int ans=0;        while(BFS())        {            memset(cur,0,sizeof(cur));            ans+=DFS(s,INF);        }        return ans;    }}DC;int K,C,M;int src,dst;int dist[maxn][maxn];void floyd(int n){    for(int k=1;k<=n;k++)    for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++)    if(dist[i][k]<INF && dist[k][j]<INF)        dist[i][j]=min(dist[i][j], dist[i][k]+dist[k][j]);}bool solve(int limit){    DC.init(K+C+2,src,dst);    for(int i=1;i<=C;i++) DC.AddEdge(src,K+i,1);    for(int i=1;i<=K;i++) DC.AddEdge(i,dst,M);    for(int i=1;i<=C;i++)    for(int j=1;j<=K;j++)    if(dist[i+K][j]<=limit)        DC.AddEdge(i+K,j,1);    return DC.max_flow()==C;}int main(){    while(scanf("%d%d%d",&K,&C,&M)==3)    {        int n=K+C;        src=0,dst=K+C+1;        for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++)            dist[i][j]= i==j?0:INF;        for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++)        {            scanf("%d",&dist[i][j]);            if(i!=j && dist[i][j]==0) dist[i][j]=INF;        }        floyd(n);        int L=0,R=0;        for(int i=1;i<=n;i++)        for(int j=i+1;j<=n;j++)        if(dist[i][j]<INF) R=max(R,dist[i][j]);        while(R>L)        {            int mid= L+(R-L)/2;            if(solve(mid)) R=mid;            else L=mid+1;        }        printf("%d\n",R);    }    return 0;}

0 0
原创粉丝点击