zoukankan      html  css  js  c++  java
  • 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
    ");
            }else
            {
                printf("%lld
    ",hi);
            }
        }
        return 0;
    }
  • 相关阅读:
    Java项目xml相关配置
    Jquery的bind跟on绑定事件的区别
    命令操作Mysql数据库
    Jquery实现功能---购物车
    Jquery插件---渐隐轮播
    Jquery制作插件---内容切换
    PCB画板的快捷键
    蓝牙2.0传数据给数码管
    蓝牙2.0传数据给数码管
    共阳极数码管计数器
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7212432.html
Copyright © 2011-2022 走看看