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

SGU 194 Reactor Cooling Dinic求解 无源无汇有上下界的最大流

时间:2016-04-02 13:28:04      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:

题目链接

题意:有向图中有n(1 <= n <= 200)个点,无自环或者环的大小至少为3.给定每条边的最小流量和最大流量,问每条边的可行流量为多少?

思路:一般求解的网络流并不考虑下界问题,即流量可以为0,在有下界时,我们只需将上界变成r-l,这时还需要满足流量守恒,增加源点s和汇点t,当点u的流入大于流出时,将点u与s连边,容量即为多出的流量。同理当u流出大于流入时,多出来的流出的流量连到汇点t;直接跑最大流;

注:这时判断是否存在可行解时,是看连到源点的所有边是否满流,全为满流说明内部流量平衡,存在可行解;之后离线对于id输出即可;

ps:对于网络流问题,无论题目的是有向还是无向图,因为是增广搜索,所以一定是建无向图。。

#include<bits/stdc++.h>
using namespace std;
#define rep0(i,l,r) for(int i = (l);i < (r);i++)
#define rep1(i,l,r) for(int i = (l);i <= (r);i++)
#define rep_0(i,r,l) for(int i = (r);i > (l);i--)
#define rep_1(i,r,l) for(int i = (r);i >= (l);i--)
#define MS0(a) memset(a,0,sizeof(a))
#define MS1(a) memset(a,-1,sizeof(a))
#define MSi(a) memset(a,0x3f,sizeof(a))
#define inf 0x3f3f3f3f
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1|1
#define lowbit(x) (x&(-x))
typedef pair<int,int> PII;
#define A first
#define B second
#define MK make_pair
typedef long long ll;
typedef unsigned int uint;
int i,j,k,n,m;
const int M = 40000;
int head[M],tot;
struct Edge{
    int from,to,cap,flow,Next,id;
    Edge(){}
    Edge(int f,int to,int cap,int Next,int id):from(f),to(to),cap(cap),Next(Next),id(id),flow(0){}
}e[M<<1];
inline void ins(int u,int v,int w,int id)
{
    e[++tot] = Edge{u,v,w,head[u],id};
    head[u] = tot;
}
int s,t,cur[M],d[222];
int que[222];
bool BFS()
{
    rep1(i,s,t) d[i] = -1;
    int l = 1,r = 1;
    que[r++] = s;d[s] = 0;
    while(l < r){ //[l,r)
        int u = que[l++];
        for(int i = head[u];i;i = e[i].Next){
            int v = e[i].to;
            if(d[v] < 0 && e[i].cap > e[i].flow){ // 只考虑残量网络的弧
                d[v] = d[u] + 1;//扑出路径来;
                que[r++] = v;
                if(v == t) return true;
            }
        }
    }
    return false;
}
int DFS(int x,int a)// a表示目前为止所有弧的最小残量
{
    if(x == t || a == 0) return a;
    int& i = cur[x];//回溯时会多次DFS到同一个点
    if(i == 0) i = head[x];
    int flow = 0, f;
    for(;i;i = e[i].Next){// 从上次考虑的弧开始
        int v = e[i].to;
        if(d[v] == d[x]+1 && (f = DFS(v,min(a,e[i].cap - e[i].flow))) > 0){
            e[i].flow += f;
            e[i^1].flow -= f;
            flow += f;
            a -= f;// 残量-流量
            if(a == 0)   break;
        }
    }
    return flow;
}
int Dinic()
{
    int flow = 0;
    while(BFS()){//仍然存在增广路时再DFS
        rep1(i,s,t) cur[i] = 0;//记录当前探索到的点的弧的编号
        flow += DFS(s,inf);

    }
    return flow;
}
int l[M],ans[M];
int main()
{
    //freopen("data.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int kase = 0;
    while(scanf("%d%d",&n,&m) == 2){
        if(kase++) puts("");
        MS0(head);tot = 1;MS0(d);
        int u,v,r;
        s = 0,t = n+1;
        rep1(i,1,m){
            scanf("%d%d%d%d",&u,&v,&l[i],&r);
            d[u] -= l[i];
            d[v] += l[i];
            ins(u,v,r-l[i],i);
            ins(v,u,0,0);
        }
        rep1(i,1,n){
            if(d[i] > 0) ins(s,i,d[i],0),ins(i,s,0,0);
            if(d[i] < 0) ins(i,t,-d[i],0),ins(t,i,0,0);
        }
        Dinic();
        bool flag = false;
        for(int d = head[s];d;d = e[d].Next){
            if(e[d].cap - e[d].flow){flag = true;break;}
        }
        if(flag){puts("NO");continue;}
        puts("YES");
        rep1(i,2,tot)if(e[i].id){
            ans[e[i].id] = e[i].flow+l[e[i].id];
        }
        rep1(i,1,m) printf("%d\n",ans[i]);
    }
    return 0;
}

 

SGU 194 Reactor Cooling Dinic求解 无源无汇有上下界的最大流

标签:

原文地址:http://www.cnblogs.com/hxer/p/5347353.html

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