[ZOJ2314]/[SGU194] Reactor Cooling 无源汇有上下界网络流

来源:互联网 发布:ppt软件下载官方 编辑:程序博客网 时间:2024/05/17 04:56

若一个图是合法的,那么除了超级源和超级汇以外的所有的点的入度流量=出度流量
新建超级源S,超级汇T
对于每一条边a,b,l,r,若将流量变为0,r-l,那么a点的出度流量减少了l,b的入度流量减少了l。那我们加入边

#include <iostream>#include <cstdio>#include <cstring>#include <queue>#define N 450#define M 2*450*450#define INF (1<<30)using namespace std;int head[N],d[N],lim[M],sp[M],p[N],n,m,S,T,cnt=1;struct Edge{ int a,b,v,next; }e[M];void init() {    cnt = 1;    memset(head,0,sizeof(head));    memset(e,0,sizeof(e));    memset(sp,0,sizeof(p));    memset(d,0,sizeof(d));    memset(lim,0,sizeof(lim));}void add(int a,int b,int v,int id) {    e[++cnt].a = a;    e[cnt].b = b;    e[cnt].v = v;    e[cnt].next = head[a];    head[a] = cnt;    sp[id] = cnt;}inline void add_Node(int a,int b,int v,int id) { add(a,b,v,id); add(b,a,0,0); }#define cp e[i].v#define B e[i].bbool BFS() {    bool flag = false;    memset(p,0,sizeof(p)); p[S] = 1;    queue<int> q; q.push(S);     while (!q.empty()) {        int u = q.front(); q.pop();        if (u == T) flag = true;        for (int i=head[u];i;i=e[i].next)             if (e[i].v>0 && !p[B]) {                p[B] = p[u]+1;                q.push(B);            }    }    return flag;}int DFS(int u,int flow) {    if (u == T) return flow;    int f = flow , g = 0 , tmp = 0;    for (int i=head[u];i;i=e[i].next) {        if (cp>0 && p[B]==p[u]+1 && ( tmp=DFS(B,min(cp,f)) ) > 0) {            e[i  ].v -= tmp;             e[i^1].v += tmp;            f -= tmp; g += tmp;        }    }    return g;}int main() {    int cas=0; scanf("%d",&cas);     while (cas--) {        scanf("%d%d",&n,&m);        init(); S = n+1; T = n+2;        for (int i=1;i<=m;i++) {            int a,b,l,r;            scanf("%d%d%d%d",&a,&b,&l,&r);            add_Node(a,b,r-l,i);            d[a] -= l; d[b] += l; lim[i] = l;        }        for (int i=1;i<=n;i++) {            if (d[i] > 0) add_Node(S,i,d[i],0);            if (d[i] < 0) add_Node(i,T,-d[i],0);        }        int flow = 0; bool flag = true;        while (BFS()) flow += DFS(S,INF);        for (int i=head[S];i;i=e[i].next)            if (e[i].v) flag = false;        if (flag) {            puts("YES");            for (int i=1;i<=m;i++)                 printf("%d\n",lim[i]+e[sp[i]^1].v);        } else puts("NO");        printf("\n");    }    return 0;} 
0 0
原创粉丝点击