上下限网络流
做法:假设有边x-y(a,b),建立临时节点ss,tt,连接x-y(0,b-a),x-ss(0,a),tt-y(0,a);
最后连接t-s(0,inf);
先对tt-ss跑最大流,如果tt的每一条边都是满流,那么就存在解,否则无解,
如果想求最大流,只需要在残余图上跑s-t的最大流,因为ss点没有出边,并且任意点到ss的流量为0,所以可以保证在残余图上跑最大流不会影响到tt-ss的流。所以可以得出答案,注意:如果用s点的出边的反向边求最大流,要注意要减去一个inf,因为连接了一条t-s(0,inf)的边。
也可以直接跑最大流、
#include<bits/stdc++.h>
using namespace std;
template<int N,typename T>
struct MaxFlow {
int s,t,head[N],etot,que[N],qf,qe,dis[N],cur[N];
struct Edge {int v,next; T cap;}g[501000];
void init() {
memset(head,-1,sizeof(head)); etot = 0;
}
void add_edge(int u,int v,T cap) {
//cout << "!!!" <<u <<' '<< v << ' '<< cap << endl;
g[etot].v = v; g[etot].next = head[u]; g[etot].cap = cap; head[u] = etot ++;
g[etot].v = u; g[etot].next = head[v]; g[etot].cap = 0; head[v] = etot ++;
}
bool bfs() {
memset(dis,-1,sizeof(dis));
memcpy(cur,head,sizeof(cur));
dis[t] = N;
qf = qe = 0;
que[qe++] = t;
while (qf!=qe) {
int u = que[qf++];
for (int i = head[u]; i != -1; i = g[i].next) {
Edge &e = g[i];
if (g[i^1].cap && dis[e.v] == -1) {
dis[e.v] = dis[u] - 1;
que[qe++] = e.v;
}
}
}
return dis[s] != -1;
}
T dfs(int u,T a) {
if (u==t) return a;
T flow = 0,f;
for (int &i = cur[u]; i != -1; i = g[i].next) {
Edge &e = g[i];
if (e.cap && dis[e.v] > dis[u]) {
f = dfs(e.v,std::min(a,e.cap));
flow += f;
e.cap -= f;
g[i^1].cap += f;
a -= f;
if (a==0) break;
}
}
if (flow==0) dis[u] = -1;
return flow;
}
T dinic(int _s,int _t) {
s = _s; t = _t;
T flow = 0;
while (bfs()) flow += dfs(s,(T)1e30);
return flow;
}
};
MaxFlow<2000+7,int> mf;
int in[2000+7];//统计每个点到ss或者到tt的流量,这里把多条边合并
int su[100000];//每个点的最小流量,最后要加上
int day[500];
int main(){
int n,m;
while(scanf("%d %d",&n,&m) == 2){
memset(in,0,sizeof(in));
int s = 0,t = n+m+1,ss = n+m+2,tt = n+m+3;
mf.init();
int tot = 0;
int inf = 1e9;
int ret = 0;
for(int i = 1;i <= m;i ++){
int now;
scanf("%d",&now);
in[n+i] -= now;
in[t] += now;
}
for(int i = 1;i <= n;i ++){
int c,d;
scanf("%d %d",&c,&d);
day[i] = d;
for(int j = 1;j <= c;j ++){
int x,l,r;
scanf("%d %d %d",&x,&l,&r);
su[tot++] = l;
mf.add_edge(i,n+x+1,r-l);//连接残余边
in[i] -= l;
in[n+x+1] += l;
}
}
for(int i = 1;i <= n;i ++) mf.add_edge(s,i,day[i]);
for(int i = 1;i <= m;i ++) mf.add_edge(n+i,t,inf);
mf.add_edge(t,s,inf);
for(int i = 0;i <= n+m+1;i ++){//处理连接ss和tt的边
if(in[i] > 0) mf.add_edge(tt,i,in[i]),ret += in[i];
if(in[i] < 0) mf.add_edge(i,ss,-in[i]);
}
int mxf = mf.dinic(tt,ss);
if(mxf == ret){
printf("%d\n",mf.dinic(s,t));
for(int i = 0;i < tot;i ++){
printf("%d\n",mf.g[i*2+1].cap+su[i]);
}
}
else puts("-1");
puts("");
}
return 0;
}