无源汇有上下界限制网络流
拆点可解
设超级源点 ss 和超级汇点 tt
deg[i] = i 点的流入容量和 - i 点的流出容量和
若 deg[i] > 0 建立 ss -> i 边权为 deg[i] 的边 强行流出 deg[i] 的流量
若 deg[i] < 0 建立 i -> tt 边权为 -deg[i] 的边 强行流入 -deg[i] 的流量
贴代码(AC,15ms)
- #include<iostream>
- #include<queue>
- #include<cstdlib>
- #include<vector>
- #include<cstring>
- #include<cstdio>
- using namespace std;
- const int INF = 0x7ffffff;
- const int MAXN = 205;
- const int MAXM = MAXN * MAXN;
- int n,m,s,t,cnt;
- bool vis[MAXN];
- int head[MAXN],deg[MAXM],dl[MAXM];
- int d[MAXN],cur[MAXN],que[MAXN];
- struct edge_{
- int from,to,cap,flow,next;
- }edge[MAXM];
- void init(){
- memset(head,-1,sizeof(head));
- memset(edge,sizeof(edge));
- memset(deg,sizeof(deg));
- cnt = 0;
- }
- void add(int from,int to,int cap){
- edge[cnt].from = from,edge[cnt].to = to;
- edge[cnt].cap = cap,edge[cnt].next = head[from];
- edge[cnt].flow = 0;
- head[from] = cnt++;
- edge[cnt].from = to,edge[cnt].to = from;
- edge[cnt].cap = 0,edge[cnt].next = head[to];
- edge[cnt].flow = 0;
- head[to] = cnt++;
- }
- bool bfs(){
- memset(vis,false,sizeof(vis));
- memset(d,sizeof(d));
- d[s] = 0,vis[s] = 1,que[0] = s;
- int tail = 0,front = 1;
- while(tail < front){
- int x = que[tail++];
- for(int now = head[x]; ~now; now = edge[now].next){
- edge_ &e = edge[now];
- if(!vis[e.to] && e.cap > e.flow){
- vis[e.to] = 1;
- d[e.to] = d[x] + 1;
- que[front++] = e.to;
- }
- }
- }
- return vis[t];
- }
- int dfs(int x,int a){
- if(x == t || a == 0)
- return a;
- int flow = 0,f;
- for(int &now = cur[x]; ~now; now = edge[now].next){
- edge_ &e = edge[now];
- if(d[x] + 1 == d[e.to] && (f = dfs(e.to,min(a,e.cap - e.flow))) > 0){
- e.flow +=f;
- edge[now ^ 1].flow -= f;
- flow += f;
- a -= f;
- if(a == 0)
- break;
- }
- }
- return flow;
- }
- int maxFlow(int _s,int _t,int _n,int _m){
- s = _s,t = _t;
- n = _n,m = _m;
- int flow = 0;
- while(bfs()){
- for(int i = 1; i <= n; i++)
- cur[i] = head[i];
- flow += dfs(s,INF);
- }
- return flow;
- }
- int main(){
- int n,l,r,ss,tt;
- while(~scanf("%d%d",&n,&m)){
- init();
- ss = n + 1,tt = n + 2;
- for(int i = 1; i <= m; ++i){
- scanf("%d%d%d%d",&s,&t,&l,&r);
- deg[s] -= l,deg[t] += l,dl[i] = l;
- add(s,r - l);
- }
- int sum = 0;
- for(int i = 1; i <= n; ++i){
- if(deg[i] > 0){
- add(ss,i,deg[i]);
- sum += deg[i];
- }
- else
- add(i,tt,-deg[i]);
- }
- if(maxFlow(ss,n + 2,m) == sum){
- printf("YES\n");
- for(int i = 0; i < m; ++i)
- printf("%d\n",edge[i * 2].flow + dl[i + 1]);
- }
- else{
- printf("NO\n");
- }
- }
- return 0;
- }