码迷,mamicode.com
首页 > 其他好文 > 详细

hdu4940 Destroy Transportation system

时间:2014-08-13 10:29:15      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:2014多校   上下界最大流   网络流   hdu   

给你一个强连通的有向简单图,每条边有D, B两个权值,设S为点集的一个非空真子集

问:是否对于任意的集合S,都有sum (D(i, j))<= sum(D(j, i) + B(j, i)),(i, j)是点集S和S‘的割边

比赛的时候完全没有思路啊。。。最大流果然还是白板


思路:将D值作为边的下界,D + B作为边的上界,如果存在可行流,那么对于任意集合S

都有流量小于等于边的容量上界,大于等于边的容量下界,即D(i, j) <= f(i, j) <= D(j, i)+B(j, i)

这就将问题转化为了裸的有下界的最大流,解决方法见这里


#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <string>
#include <set>
#include <stack>
#include <map>
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
#include <bitset>
#include <fstream>
using namespace std;
//LOOP
#define FF(i, a, b) for(int i = (a); i < (b); ++i)
#define FE(i, a, b) for(int i = (a); i <= (b); ++i)
#define FED(i, b, a) for(int i = (b); i>= (a); --i)
#define REP(i, N) for(int i = 0; i < (N); ++i)
#define CLR(A,value) memset(A,value,sizeof(A))
//OTHER
#define PB push_back
//INPUT
#define RI(n) scanf("%d", &n)
#define RII(n, m) scanf("%d%d", &n, &m)
#define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k)
#define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p)

#define sqr(x) (x) * (x)
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> VI;
const double eps = 1e-9;
const int MOD = 1000000007;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int maxn = 250;

/////Dinic算法//////
struct Edge{
    int from, to, cap, flow;
};

struct Dinic{
    int n, m ,s, t;
    vector<Edge> edges;
    VI G[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn]   ;

    void init(int nn)
    {
        this->n = nn;
        REP(i, n + 2) G[i].clear();
        edges.clear();
    }

    void addEdge(int from, int to, int cap)
    {
        edges.PB((Edge){from, to, cap, 0});
        edges.PB((Edge){to, from, 0, 0});
        m = edges.size();
        G[from].PB(m - 2);
        G[to].PB(m - 1);
    }

    bool bfs()
    {
        CLR(vis, 0);
        queue<int> Q;
        Q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while (!Q.empty())
        {
            int x = Q.front();
            Q.pop();
            REP(i, G[x].size())
            {
                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;
    }
    //当所求流量大于need时就退出,降低时间
    int maxflow(int s,int t,int need){
        this->s = s; this->t = t;
        int flow = 0;
        while(bfs())
        {
            CLR(cur ,0);
            flow += dfs(s,INF);
            if (flow > need)
                return flow;
        }
        return flow;
    }
    //最小割割边
    vector<int> Mincut(){
        BFS();
        vector<int> ans;
        for (int i = 0; i < edges.size(); i++){
            Edge& e = edges[i];
            if (vis[e.from] && !vis[e.to] && e.cap > 0)
        ans.push_back(i);
        }
        return ans;
    }
    void Reduce(){
        for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow;
    }
    void ClearFlow(){
        for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
    }
}sol;

int sum[maxn];

int main()
{
    //freopen("0.txt", "r", stdin);
    int T, x, y, b, d, tot;
    int n, m;
    RI(T);
    FE(kase, 1, T)
    {
        CLR(sum, 0), tot = 0;
        RII(n, m);
        sol.init(n + 2);
        REP(i, m)
        {
            RIV(x, y, d, b);
            sum[x] -= d;
            sum[y] += d;
            sol.addEdge(x, y, b);
        }
        FE(i, 1, n)
            if (sum[i] > 0)
                sol.addEdge(0, i, sum[i]), tot += sum[i];
            else if (sum[i] < 0)
                sol.addEdge(i, n + 1, -sum[i]);
        int ans = sol.maxflow(0, n + 1, INF);
        printf("Case #%d: ", kase);
        if (ans == tot)
            puts("happy");
        else
            puts("unhappy");
    }
    return 0;
}



hdu4940 Destroy Transportation system,布布扣,bubuko.com

hdu4940 Destroy Transportation system

标签:2014多校   上下界最大流   网络流   hdu   

原文地址:http://blog.csdn.net/colin_27/article/details/38532709

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!