poj2391 Ombrophobic Bovines 拆点+二分法+最大流

/**
题目:poj2391 Ombrophobic Bovines
链接:http://poj.org/problem?id=2391
题意:有n块区域,第i块区域有ai头奶牛,以及一个可以容纳bi头奶牛的棚子。n块区域由m条可以容纳无数奶牛经过的双向通道相连,给定奶牛通过通道的时间。
问所有奶牛回到棚子需要的最短时间。
思路:。。。我好菜哦。没想到,看了blog才知道怎么做。

先用floyd求得两块区域相通最短时间。

将点x拆分成x,x'。源点s连接x,容量为x的奶牛数。x'连接汇点t容量为x的棚子容纳数。

二分一个时间time,表示需要的最短时间。无论奶牛在哪个地方,只要从该点出发,距离time以内的点都可以到达。

所以如果x点到y点的最短时间<=time。那么x连接y',容量为INF。

对这个二分图求最大流。如果最大流=总奶牛数量。那么表示该时间内可行。

注意时间!超int。

*/
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const long long MAS = 1e13;
const int INF = 0x3f3f3f3f;
typedef long long LL;
const int N = 405;///
struct Edge{
    int from, to, cap, flow;
    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
struct Dinic{
    int n, m, s, t;
    vector<Edge> edges;
    vector<int> G[N];
    bool vis[N];
    int d[N];
    int cur[N];

    void init(int n)
    {
        this->n = n;
        for(int i = 0; i <= n; i++) G[i].clear();
        edges.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()
    {
        memset(vis, 0, sizeof vis);
        queue<int> Q;
        Q.push(s);
        d[s] = 0;
        vis[s] = 1;
        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] = 1;
                    d[e.to] = d[x]+1;
                    Q.push(e.to);
                }
            }
        }
        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[x]+1==d[e.to]&&(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 Maxflow(int s,int t)
    {
        this->s = s, this->t = t;
        int flow = 0;
        while(BFS())
        {
            memset(cur, 0, sizeof cur);
            flow += DFS(s,INF);
        }
        return flow;
    }
};
LL f[N][N];
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++){
                f[i][j] = min(f[i][j],f[i][k]+f[k][j]);
            }
        }
    }
}
int main()
{
    int n, m, sum;
    while(scanf("%d%d",&n,&m)==2)
    {
        int s = 0, t = n*2+1;
        Dinic dinic;
        dinic.init(t);
        sum = 0;
        int flow, cap;
        for(int i = 1; i <= n; i++){
            scanf("%d%d",&flow,&cap);
            sum += flow;
            dinic.AddEdge(s,i,flow);
            dinic.AddEdge(i+n,t,cap);
            dinic.AddEdge(i,i+n,INF);
        }
        int u, v;
        LL time;
        for(int i = 1; i <= n ; i++)
            for(int j = 1; j <= n; j++)
                f[i][j] = MAS;
        for(int i = 1; i <= m; i++){
            scanf("%d%d%lld",&u,&v,&time);
            f[u][v] = min(f[u][v],time);
            f[v][u] = f[u][v];
        }
        floyd(n);
        Dinic Save = dinic;
        LL lo = 0, hi = MAS, mid;
        while(lo<hi){
            mid = (lo+hi)/2;
            dinic = Save;
            for(int i = 1; i <= n; i++){
                for(int j = 1; j <= n; j++){
                    if(f[i][j]<=mid){
                        dinic.AddEdge(i,j+n,INF);
                    }
                }
            }
            int masflow = dinic.Maxflow(s,t);
            if(masflow==sum){
                hi = mid;
            }else
            {
                lo = mid+1;
            }
        }
        if(hi==MAS){
            printf("-1\n");
        }else
        {
            printf("%lld\n",hi);
        }
    }
    return 0;
}

 

posted on 2017-07-20 17:30  hnust_accqx  阅读(151)  评论(0编辑  收藏  举报

导航