zoukankan      html  css  js  c++  java
  • HDU 4940 Destroy Transportation system(2014 Multi-University Training Contest 7)

    思路:无源汇有上下界可行流判定, 原来每条边转化成  下界为D  上界为 D+B   ,判断是否存在可行流即可。

    为什么呢?  如果存在可行流  那么说明对于任意的 S 集合流出的肯定等于 流入的, 流出的计算的 X 肯定小于等于这个流量(X是下界之和), 计算出来的Y (上界之和)肯定大于等于 这个流量  肯定满足X<=Y。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include <iostream>
    #include<climits>
    using namespace std;
    const int N = 1000;
    const int M = 100000;
    int n;
    int ecnt, head[N], nx[M], to[M], va[M], cur_edge[N];
    int source, target, flow, pre[N], lev[N], qu[N], sign;
    void addedge(int u, int v, int w) {
        to[ecnt] = v;
        nx[ecnt] = head[u];
        va[ecnt] = w;
        head[u] = ecnt++;
    }
    bool bfs(int s, int t) {
        std::fill(lev, lev + n, -1);
        sign = t;
        lev[t] = 0;
        int st = 0, ed = 0;
        qu[ed++] = t;
        while (st != ed && lev[s] == -1) {
            int u = qu[st++];
            for (int i = head[u]; i != -1; i = nx[i]) {
                if (va[i ^ 1] > 0 && lev[to[i]] == -1) {
                    lev[to[i]] = lev[u] + 1;
                    qu[ed++] = to[i];
                }
            }
        }
        return lev[s] != -1;
    }
    void push() {
        int delta = INT_MAX, u, p;
        for (u = target; u != source; u = to[p ^ 1]) {
            p = pre[u];
            delta = std::min(delta, va[p]);
        }
        for (u = target; u != source; u = to[p ^ 1]) {
            p = pre[u];
            va[p] -= delta;
            if (!va[p]) {//注意double时要改
                sign = to[p ^ 1];
            }
            va[p ^ 1] += delta;
        }
        flow += delta;
    }
    void dfs(int u) {
        if (u == target)
            push();
        else {
            for (int i = cur_edge[u]; i != -1; i = nx[i]) {
                if (va[i] > 0 && lev[u] == lev[to[i]] + 1) {
                    pre[to[i]] = i;
                    dfs(to[i]);
                    if (lev[sign] > lev[u]) {
                        return;
                    }
                    sign = target;
                }
            }
            lev[u] = -1;
        }
    }
    int nc, pc, tc;
    int lx[M], ly[M], lv[M];
    void dinic(int s, int t, int node_cnt) {
        source = s;
        target = t;
        n = node_cnt;
    
        //construct graph
    
        flow = 0;
        while (bfs(source, target)) {
            for (int i = 0; i < n; ++i) {
                cur_edge[i] = head[i];
            }
            dfs(source);
        }
    
    }
    int in[500],out[500];
    void solve() {
        int n,m;
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        scanf("%d%d",&n,&m);
        fill(head,head+n+10,-1);
        ecnt=0;
        for(int i=0;i<m;++i)
        {
            int u,v,x,y;
            scanf("%d%d%d%d",&u,&v,&x,&y);
            in[v]+=x;
            in[u]-=x;
            addedge(u,v,y);
            addedge(v,u,0);
        }
        int s,t;
        s=0;t=n+1;
        int sum=0;
        for(int i=1;i<=n;++i)
        {
            if(in[i]>0)
            {
                sum+=in[i];
                addedge(s,i,in[i]);
                addedge(i,s,0);
            }
            else
            {
                addedge(i,t,-in[i]);
                addedge(t,i,0);
            }
        }
        dinic(s,t,t+2);
        if(flow==sum)puts("happy");
        else puts("unhappy");
    }
    int main() {
        int ri=0,tt;
        scanf("%d",&tt);
        while(tt--)
        {
            printf("Case #%d: ",++ri);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    VirtualBox设置共享文件夹和镜像访问的方法
    虚拟机文件越来越大解决方案
    linux磁盘清理方法 Linux 下垃圾清理工具 BleachBit
    linux上怎么切换不同版本的arm-linux-gcc?只需改一行函数
    windows桌面添加右键环境
    各种机械键盘轴的差别,究竟什么轴好
    XML是什么,它能够做什么?——写给XML入门者
    MATLAB中导入数据:importdata函数
    理解ThreadLocal
    Leetcode:best_time_to_buy_and_sell_stock_II题解
  • 原文地址:https://www.cnblogs.com/L-Ecry/p/3908004.html
Copyright © 2011-2022 走看看