sgu 176 Flow construction(有源汇的上下界最小流)

时间:2023-03-08 21:30:33

【题目链接】

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11025

【模型】

有源汇点的上下界最小流。即既满足上下界又满足流量平衡的最小流量。

【思路】

按照可行流构造网络。不连t->s的边先跑一遍附加源汇点的最大流,然后连t->s一条inf边,在残量网络上跑一遍最大流。第一次求最大流所以能走的边都已经流满,第二次求附加源汇点最大流t->s的流量就会尽可能小。

另外还可以二分下界mid,然后连边(T,S,mid),如果存在可行流则mid可行。

【代码】

 #include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
const int N = 5e4+;
const int inf = 1e9; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct Edge {
int u,v,cap,flow;
Edge(int u=,int v=,int cap=,int flow=)
:u(u),v(v),cap(cap),flow(flow){}
};
struct Dinic {
int n,m,s,t;
int d[N],cur[N],vis[N];
vector<int> g[N];
vector<Edge> es;
queue<int> q;
void init(int n) {
this->n=n;
es.clear();
FOR(i,,n) g[i].clear();
}
void clear() {
FOR(i,,(int)es.size()-) es[i].flow=;
}
void AddEdge(int u,int v,int w) {
es.push_back(Edge(u,v,w,));
es.push_back(Edge(v,u,,));
m=es.size();
g[u].push_back(m-);
g[v].push_back(m-);
}
int bfs() {
memset(vis,,sizeof(vis));
q.push(s); d[s]=; vis[s]=;
while(!q.empty()) {
int u=q.front(); q.pop();
FOR(i,,(int)g[u].size()-) {
Edge& e=es[g[u][i]];
int v=e.v;
if(!vis[v]&&e.cap>e.flow) {
vis[v]=;
d[v]=d[u]+;
q.push(v);
}
}
}
return vis[t];
}
int dfs(int u,int a) {
if(u==t||!a) return a;
int flow=,f;
for(int& i=cur[u];i<g[u].size();i++) {
Edge& e=es[g[u][i]];
int v=e.v;
if(d[v]==d[u]+&&(f=dfs(v,min(a,e.cap-e.flow)))>) {
e.flow+=f;
es[g[u][i]^].flow-=f;
flow+=f; a-=f;
if(!a) break;
}
}
return flow;
}
int MaxFlow(int s,int t) {
this->s=s,this->t=t;
int flow=;
while(bfs()) {
memset(cur,,sizeof(cur));
flow+=dfs(s,inf);
}
return flow;
}
} dc; int n,m,sum,down[N],in[N],id[N]; int main()
{
while(scanf("%d%d",&n,&m)==) {
sum=;
int S=,T=n+;
dc.init(T+);
memset(in,,sizeof(in));
FOR(i,,m) {
id[i]=-;
int x=read(),y=read(),z=read(),c=read();
if(c) down[i]=z,sum+=z,dc.AddEdge(S,y,z),dc.AddEdge(x,T,z);
else down[i]=,dc.AddEdge(x,y,z),id[i]=dc.es.size()-;
}
int flow=dc.MaxFlow(S,T);
dc.AddEdge(n,,inf);
flow+=dc.MaxFlow(S,T);
if(flow!=sum) puts("Impossible");
else {
printf("%d\n",dc.es[dc.es.size()-].flow);
FOR(i,,m-)
if(id[i]>=) printf("%d ",dc.es[id[i]].flow+down[i]);
else printf("%d ",down[i]);
if(id[m]>=) printf("%d\n",dc.es[id[m]].flow+down[m]);
else printf("%d\n",down[m]);
}
}
return ;
}