加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

ZOJ 2314 无源点汇点 有上下界的可行流

(2011-08-12 11:26:16)
标签:

无源汇点

有上下界可行流

it

分类: 网络流

题目描述:

输入ttcase

输入nmn点,m边。

m行,fromtolr4个整数,fromto,下界l,上界r

没有可行流,输出no,否则,输入一种方案:原来每条边的距离流量是多少。

解题报告:

输入边的时候,对每个节点求出M[i],表示流入节点i的下界总和 减去 流出节点i的下界总和。

构图如下:

新建源点s,汇点t

对于图中原来的边ij,连接ij,容量为r – l(上界减下界)

如果M[i] >= 0,连接si,容量M[i].

否则,连接it,容量-M[i]

st的最大流。

如果源点或者汇点有一方满流,就存在可行解,否则不存在。

可行解为,当前边的流量加上这条边的下界。

讲解见周源的研究报告

代码如下:

//edge加了idlow变量,用于输出而已。

#include<iostream>

#include<cstring>

#include<vector>

#include<algorithm>

#include<cmath>

#include<cstdio>

using namespace std;

#define Max 0x1fffffff

#define SIZE 210

struct edge{int from, to, val, next, id, low;}e[550000];

int v[SIZE], que[SIZE], dis[SIZE], cnt, cur[SIZE], M[SIZE];

void insert(int from, int to, int va, int id, int low)

{

    e[cnt].from = from, e[cnt].to = to; e[cnt].val = va;

    e[cnt].low = low;

    e[cnt].next = v[from]; e[cnt].id = id; v[from] = cnt++;

    e[cnt].from = to, e[cnt].to = from; e[cnt].val = 0;

    e[cnt].next = v[to];v[to] = cnt++;

}

bool bfs(int n, int s, int t)

{

    int head, tail, id;

    head = tail = 0; que[tail++] = s;

    memset(dis, -1, sizeof(int) * n);dis[s] = 0;

    while(head < tail) // bfs,得到顶点i的距s的最短距离dis[i]

        for(id = v[que[head++]]; id != -1; id = e[id].next)

            if (e[id].val > 0 && dis[e[id].to] == -1)

            {

                dis[e[id].to] = dis[e[id].from] + 1;

                que[tail++] = e[id].to;

                if (e[id].to == t) return true;

            }

    return false;

}

int Dinic(int n, int s, int t)

{

    int maxflow = 0, tmp, i;

    while(bfs(n, s, t))

    {

        int u = s, tail = 0;

        for(i = 0; i < n; i++) cur[i] = v[i];

        while(cur[s] != -1)

            if (u != t && cur[u] != -1 && e[cur[u]].val > 0 && dis[u] != -1 && dis[u] + 1 == dis[e[cur[u]].to])

            {que[tail++] = cur[u]; u = e[cur[u]].to;}

            else if (u == t)

            {

                for(tmp = Max, i = tail - 1; i >= 0; i--) tmp = min(tmp, e[que[i]].val);

                for(maxflow += tmp, i = tail - 1; i >= 0; i--)

                {

                    e[que[i]].val -= tmp;

                    e[que[i] ^ 1].val += tmp;

                    if (e[que[i]].val == 0) tail = i;

                }

                u = e[que[tail]].from;

            }

            else

            {

                while(tail > 0 && u != s && cur[u] == -1) u = e[que[--tail]].from;

                cur[u] = e[cur[u]].next;

            }

    }

    return maxflow;

}

int n, m;

bool solve()

{

    scanf("%d%d", &n, &m);

    memset(M, 0, sizeof(M)); memset(v, -1, sizeof(v)); cnt = 0;

    int s = 0, t = n + 1;

    for(int i = 0; i < m; i++)

    {

        int from, to, l, r;

        scanf("%d%d%d%d", &from, &to, &l, &r);

        insert(from, to, r - l, i, l);

        M[to] += l; M[from] -= l;

    }

    for(int i = 1; i <= n; i++)

        if (M[i] >= 0) insert(s, i, M[i], -1, -1);

        else insert(i, t, -M[i], -1, -1);

    Dinic(t + 1, s, t);

    bool flag1 = true, flag2 = true;

    for(int i = v[s]; i != -1; i = e[i].next)

        if (e[i].val != 0){flag1 = false; break;}

    for(int i = v[t]; i != -1; i = e[i].next)

        if (e[i^1].val != 0){flag2 = false; break;}

    return flag1 || flag2;

}

int ans[SIZE * SIZE];

int main()

{

    int t;scanf("%d", &t);

    while(t--)

    {

        if (solve())

        {

            printf("YES\n");

            for(int i = 0; i < cnt; i += 2) if (e[i].id >= 0)

                ans[e[i].id] = e[i^1].val + e[i].low;

            for(int i = 0; i < m; i++)

                printf("%d\n", ans[i]);

            printf("\n");

        }else printf("NO\n\n");

    }

         return 0;

}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有