ZOJ2314 Reactor Cooling

传送门

题目大意:给定N(N<=200)个节点和M(范围未知)个管子。每个管子有一个流量的上限和下限(<=100000),求是否能在网络中形成可行流。如果能的话,还要输出每条管子中的流量。

上下界网络流之可行流……这个就是比较基本的模板了。我们统计一下从每个点流入,流出的下限,之后建立辅助原点和辅助汇点,然后对于每个点,用流出下限减去流入下限,如果大于0就向辅助汇点连接容量为差值的边。否则向辅助源点连接容量为差值的绝对值的边。原图中每一条边的容量取上届减去下届的差值。

之后图建好了,直接从辅助源点到辅助汇点跑最大流,判断这个最大流是否与从原点流出的流量相等。如果相等就说明有可行流,否则没有。

这样就结束了,注意在复制head数组的时候不要复制少了。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
#define fr friend inline
#define y1 poj
#define mp make_pair
#define pr pair<int,int>
#define fi first
#define sc second
#define pb push_back

using namespace std;
typedef long long ll;
const int M = 100005;
const int N = 205;
const int INF = 1000000009;
const double eps = 1e-7;

int read()
{
   int ans = 0,op = 1;char ch = getchar();
   while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
   while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
   return ans * op;
}

struct edge
{
   int next,to,from,v;
}e[M<<1];

int Ti,n,m,head[N<<1],ecnt,x,y,a[M<<1],b[M<<1],rsum[N<<1],csum[N<<1],S,T,tot,dep[N<<1],cur[N<<1];
queue <int> q;

void add(int x,int y,int z)
{
   e[++ecnt].to = y;
   e[ecnt].next = head[x];
   e[ecnt].v = z;
   head[x] = ecnt;
}

void clear()
{
   memset(head,-1,sizeof(head)),ecnt = -1,tot = 0;
   rep(i,S,T) rsum[i] = csum[i] = 0;
}

bool bfs(int s,int t)
{
   while(!q.empty()) q.pop();
   rep(i,s,t) cur[i] = head[i];
   memset(dep,-1,sizeof(dep));
   dep[s] = 0,q.push(s);
   while(!q.empty())
   {
      int k = q.front();q.pop();
      for(int i = head[k];~i;i = e[i].next)
      {
	 if(e[i].v && dep[e[i].to] == -1)
	    dep[e[i].to] = dep[k] + 1,q.push(e[i].to);
      }
   }
   return dep[t] != -1;
}

int dfs(int s,int t,int lim)
{
   if(s == t || !lim) return lim;
   int flow = 0;
   for(int i = cur[s];~i;i = e[i].next)
   {
      cur[s] = i;
      if(dep[e[i].to] != dep[s] + 1) continue;
      int f = dfs(e[i].to,t,min(lim,e[i].v));
      if(f)
      {
	 e[i].v -= f,e[i^1].v += f;
	 flow += f,lim -= f;
	 if(!lim) break;
      }
   }
   if(!flow) dep[s] = -1;
   return flow;
}

int dinic(int s,int t)
{
   int maxflow = 0;
   while(bfs(s,t)) maxflow += dfs(s,t,INF);
   return maxflow;
}

int main()
{
   Ti = read();
   while(Ti--)
   {
      n = read(),m = read(),T = n + 1;
      clear();
      rep(i,0,m-1)
      {
	 x = read(),y = read(),a[i] = read(),b[i] = read(),add(x,y,b[i]-a[i]),add(y,x,0);
	 rsum[y] += a[i],csum[x] += a[i];
      }
      rep(i,1,n)
      {
	 int now = csum[i] - rsum[i];
	 if(now < 0) add(S,i,-now),add(i,S,0);
	 else add(i,T,now),add(T,i,0),tot += now;
      }
      if(tot != dinic(S,T)) printf("NO\n");
      else
      {
	 printf("YES\n");
	 rep(i,0,m-1) printf("%d\n",e[i<<1|1].v + a[i]);
      }
   }
   return 0;
}

posted @ 2018-12-18 00:03  CaptainLi  阅读(99)  评论(0编辑  收藏  举报