【费用流】[BZOJ1061]/[HYSBZ1061]志愿者招募
2016-01-05 22:05
357 查看
题目
分析:建图的方法还是比较难想。
首先,计算两个相邻时刻的差分,若a[i] < a[i-1],就从i向汇点连边,容量为a[i-1]-a[i],若a[i] > a[i-1],就从源点向i连边,容量为a[i]-a[i-1]
请联系差分数组理解。
然后,对于志愿者,连s->(t+1),容量为+∞,费用为c。
最后,由于志愿者可以多不能少,连(i+1)->i,容量为+∞。
跑费用流算出费用即可。
分析:建图的方法还是比较难想。
首先,计算两个相邻时刻的差分,若a[i] < a[i-1],就从i向汇点连边,容量为a[i-1]-a[i],若a[i] > a[i-1],就从源点向i连边,容量为a[i]-a[i-1]
请联系差分数组理解。
然后,对于志愿者,连s->(t+1),容量为+∞,费用为c。
最后,由于志愿者可以多不能少,连(i+1)->i,容量为+∞。
跑费用流算出费用即可。
[code]#include<cstdio> #include<algorithm> #include<cstring> #include<queue> #define MAXN 1000 #define MAXM 10000 #define INF 0x7f7f7f7f7f7f7f7fll using namespace std; deque<int>q; void Read(int &x){ char c; while(c=getchar(),c!=EOF) if(c>='0'&&c<='9'){ x=c-'0'; while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0'; ungetc(c,stdin); return; } } int n,m,S,T,a[MAXN+10]; typedef long long LL; LL dist[MAXN+10],cost; bool vis[MAXN+10]; struct node{ int wt,v; LL cap; node *next,*back; }*adj[MAXN+10],edge[MAXN*4+MAXM*2+10],*ecnt=edge,*pre[MAXN+10]; template<class T> void Read(T &x){ char c; while(c=getchar(),c!=EOF) if(c>='0'&&c<='9'){ x=c-'0'; while(c=getchar(),c>='0'&&c<='9') x=x*10+c-'0'; ungetc(c,stdin); return; } } void addedge(int u,int v,int wt,LL cap){ node *p=++ecnt; p->v=v; p->wt=wt; p->cap=cap; p->next=adj[u]; adj[u]=p; p=p->back=++ecnt; p->v=u; p->wt=-wt; p->cap=0; p->next=adj[v]; adj[v]=p; p->back=ecnt-1; } void read(){ Read(n),Read(m); int i,s,t,c; T=n+2; for(i=1;i<=n;i++) Read(a[i]); for(i=1;i<=n;i++){ if(a[i]>a[i-1]) addedge(S,i,0,a[i]-a[i-1]); else if(a[i]<a[i-1]) addedge(i,T,0,a[i-1]-a[i]); addedge(i+1,i,0,INF); } addedge(n+1,T,0,a ); for(i=1;i<=m;i++){ Read(s),Read(t),Read(c); addedge(s,t+1,c,INF); } } bool spfa(){ memset(dist,0x7f,sizeof dist); memset(pre,0,sizeof pre); q.push_back(S); vis[S]=1; dist[S]=0; int u,v,len; LL sum; while(!q.empty()){ u=q.front(); q.pop_front(); if(dist[u]*len>sum){ q.push_back(u); continue; } len--; sum-=dist[u]; vis[u]=0; for(node *p=adj[u];p;p=p->next){ v=p->v; if(p->cap>0&&dist[v]>dist[u]+p->wt){ dist[v]=dist[u]+p->wt; pre[v]=p; if(!vis[v]){ vis[v]=1; if(q.empty()||dist[v]>dist[q.front()]) q.push_back(v); else q.push_front(v); sum+=dist[v]; len++; } } } } if(dist[T]==INF) return 0; return 1; } void mcmf(){ int u; LL delta; while(spfa()){ delta=INF; for(u=T;u!=S;u=pre[u]->back->v) delta=min(delta,pre[u]->cap); for(u=T;u!=S;u=pre[u]->back->v){ pre[u]->cap-=delta; pre[u]->back->cap+=delta; cost+=delta*pre[u]->wt; } } } int main() { read(); mcmf(); printf("%lld\n",cost); }
相关文章推荐
- Qt多线程学习:创建多线程
- IOS中随机数的获取
- Linux下ARM SoC信息描述
- JS_变量
- JavaScript学习之旅--this指向问题
- java异常
- 畅通工程续floyd
- 自定义类型转换器
- Leetcode__Maximum depth
- UE4 创建自己的角色
- UE4 创建自己的角色
- /usr/local/MATLAB/R2013a/sys/os/glnxa64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found 解决方法
- ADO 连接 服务器Oracle
- STL 概述
- Middleware
- Leetcode__Maximum depth
- css+JS实现遮罩弹框
- BZOJ 2124等差子序列 线段树&&hash
- nodejs review-03
- UC/OS基础知识之任务的创建