题目传送门
分析:
这个好像和那道清理滑雪跑道好像啊。。。
如果每个点都要访问恰好Fi次
然后边不能超过w次
哦。。。
上下界网络流
每个点拆成两个,原点向复制点连上(F,F)的边,复制点向可到达的原点连(0,w)的边
由于公交可以到达每个点,相当于发配流量,每个点都可以停下,相当于直接流向终点
所以S向每个原点连(0,INF)的边,每个复制点向T连(0,INF)的边
然后直接跑就好了。。。

#include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #define maxn 20005 #define maxm 2000005 #define INF 0x3f3f3f3f using namespace std; inline int getint() { int num=0,flag=1;char c; while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1; while(c>='0'&&c<='9')num=num*10+c-48,c=getchar(); return num*flag; } int n,m,S,T; int fir[maxn],nxt[maxm],to[maxm],cap[maxm],cnt; int h[maxn],tp[maxn]; int f[maxn]; long long ans; inline void newnode(int u,int v,int w) {to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,cap[cnt]=w;} inline void insert(int u,int v,int w) {newnode(u,v,w),newnode(v,u,0);} inline bool bfs() { memset(h,-1,sizeof h); queue<int>Q;h[S]=0,Q.push(S); while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=fir[u];i;i=nxt[i]) if(cap[i]&&!~h[to[i]])h[to[i]]=h[u]+1,Q.push(to[i]); } return ~h[T]; } inline int dfs(int u,int flow) { if(u==T)return flow; int used=0; for(int i=tp[u];i;i=nxt[i]) { tp[u]=i; if(cap[i]&&h[to[i]]==h[u]+1) { int w=flow-used; w=dfs(to[i],min(cap[i],w)); cap[i]-=w,cap[i^1]+=w,used+=w; if(used==flow)return flow; } } if(!used)h[u]=-1; return used; } inline int dinic() { int num=0; while(bfs())memcpy(tp,fir,sizeof fir),num+=dfs(S,INF); return num; } int main() { n=getint(),m=getint(); S=2*n+1,T=S+1;cnt=1; for(int i=1;i<=n;i++) { int x=getint(); f[i]-=x,f[i+n]+=x; insert(S,i,50000),insert(i+n,T,50000); } for(int i=1;i<=m;i++) { int u=getint(),v=getint(),w=getint(); insert(u+n,v,w); } int SS=T+1,TT=SS+1; for(int i=1;i<=T;i++) if(f[i]>0)insert(SS,i,f[i]); else insert(i,TT,-f[i]); insert(T,S,INF); S=SS,T=TT; dinic(); printf("%d ",cap[cnt]); }