有意思的网络流
最小费用最大流 建边很讲究
/************************************************************** Problem: 1061 User: lxy8584099 Language: C++ Result: Accepted Time:144 ms Memory:4600 kb ****************************************************************/ /* 网络流 最小费用最大流 最坏 n*m建图 走到这个人花费cost 无限大流 这个人到自己可以看管的天 花费0 无限大流 天数到ed 花费0 流是需要的人数 没错 以上是错解,,, 应该是 st连第一天 0,inf 最后一天连ed 0,inf 每个人s连e+1 cost inf i连i+1 0,inf-a[i] 这样当人数不够的时候 就有相应的最小cost去补齐 */ #include<bits/stdc++.h> #define inf (0x3fffffff) using namespace std; typedef long long ll; const int N=1e4+50; struct pp{int v,nxt,d,c;} e[N*20]; int n,m,tot=1,head[N],st,ed; int from[N]; ll dis[N],ans; bool vis[N]; void add(int u,int v,int d,int c) { e[++tot].nxt=head[u];head[u]=tot; e[tot].v=v;e[tot].d=d;e[tot].c=c; e[++tot].nxt=head[v];head[v]=tot; e[tot].v=u;e[tot].d=-d;e[tot].c=0; } bool Spfa() { queue<int> q; q.push(st); memset(dis,0x3f,sizeof(dis)); long long mx=dis[0]; dis[st]=0; while(!q.empty()) { int u=q.front();q.pop(); vis[u]=0; for(int j=head[u];j;j=e[j].nxt) if(e[j].c>0) { int v=e[j].v,d=e[j].d; if(dis[v]>dis[u]+d) { dis[v]=dis[u]+d,from[v]=j; if(!vis[v]) {q.push(v);vis[v]=1;} } } } if(dis[ed]==mx) return 0; int mn=inf; for(int x=ed,j;x!=st;x=e[j^1].v) j=from[x],mn=min(mn,e[j].c); ans+=dis[ed]*mn; for(int x=ed,j;x!=st;x=e[j^1].v) j=from[x],e[j].c-=mn,e[j^1].c+=mn; return 1; } int main() { scanf("%d%d",&n,&m); st=n+2,ed=st+1; add(st,1,0,inf),add(n+1,ed,0,inf); for(int i=1,x;i<=n;i++) { scanf("%d",&x); add(i,i+1,0,inf-x); } for(int i=1,u,v,cost;i<=m;i++) { scanf("%d%d%d",&u,&v,&cost); add(u,v+1,cost,inf); } while(Spfa()); printf("%lld\n",ans); return 0; }