SDUT 2414 An interesting game(最大费用流)
2016-03-20 20:37
525 查看
题目大意:给定初始的n个山坡,并且有m个可加的山坡,选其中的不超过k个山坡来,放入n个山坡中不能够(两两的中间)。问最后加入不超过k个山坡的高度差之和。
思路:将其中的n个山坡与原点联,n个山坡再与m个山坡高度联(0<=h<=30)直接哈希一下费用为abs(a[i]-j)+abs(a[i+1]-j)-abs(a[i]-a[i+1]),然后m个山坡的高度再与汇点前一个点联流量为该座山的使用次数,最后联汇点流量为k.
思路:将其中的n个山坡与原点联,n个山坡再与m个山坡高度联(0<=h<=30)直接哈希一下费用为abs(a[i]-j)+abs(a[i+1]-j)-abs(a[i]-a[i+1]),然后m个山坡的高度再与汇点前一个点联流量为该座山的使用次数,最后联汇点流量为k.
#include<map> #include<queue> #include<cmath> #include<cstdio> #include<stack> #include<iostream> #include<cstring> #include<algorithm> #define LL long long #define inf 0x3f3f3f3f #define eps 1e-8 #define ls l,mid,rt<<1 #define rs mid+1,r,rt<<1|1 const double PI=acos(-1.0); using namespace std; struct node{ int to,w,c,next; }q[100000*5]; int head[1000000]; int st,ed,cnt,maxcost; void add(int a,int b,int w,int c){ q[cnt].to = b; q[cnt].w = w; q[cnt].c = c; q[cnt].next = head[a]; head[a] = cnt++; q[cnt].to = a; q[cnt].w = 0; q[cnt].c = -c; q[cnt].next = head[b]; head[b] = cnt++; } int ha[40],dis[2010],flow; int a[2010],f[2010],cur[2010]; bool vis[2010]; bool SPFA(){ memset(dis,inf,sizeof(dis)); memset(vis,false,sizeof(vis)); memset(cur,-1,sizeof(cur)); queue<int>Q; while(!Q.empty()) Q.pop(); Q.push(st); f[st]=inf; dis[st]=0; vis[st] = true; while(!Q.empty()){ int u = Q.front(); Q.pop(); vis[u] = false; for(int i = head[u];~i;i=q[i].next){ int v = q[i].to; if(dis[v] > dis[u] + q[i].c &&q[i].w > 0){ dis[v] = dis[u] + q[i].c; cur[v] = i; f[v] = min(f[u],q[i].w); if(!vis[v]){ vis[v] = true; Q.push(v); } } } } return dis[ed] != inf; } int so(){ int ant=0; for(int i = ed;i != st;i = q[cur[i]^1 ].to){ q[cur[i] ].w -= 1; q[cur[i]^1 ].w +=1; ant += q[cur[i] ].c; } return ant; } int main(){ int n,m,i,j,k,cla; scanf("%d",&cla); for(int zu = 1;zu <= cla;++ zu){ memset(ha,0,sizeof(ha)); maxcost=flow=cnt=st=0; int ans=0; memset(head,-1,sizeof(head)); memset(vis,false,sizeof(vis)); scanf("%d%d%d",&n,&m,&k); for(i = 1;i <= n;++ i ){ scanf("%d",&a[i]); } for(i = 1;i <= m;++ i){ scanf("%d",&j); ++ ha[j]; } for(i = 1 ;i < n;++ i){ add(st,i,1,0); } for(i = 1;i < n;i ++){ ans+=abs(a[i]-a[i+1]); for(j = 0 ;j <= 30;++ j) if(ha[j]) add(i,n + j,1,-(abs(a[i]-j)+abs(a[i+1]-j)-abs(a[i+1]-a[i]))); } ed = n + 41; for( i = 0;i <= 30 ;++ i ) if(ha[i]) add(i + n,ed-1,ha[i],0); add(ed-1,ed,k,0); int tmp=0; while(SPFA()){ tmp += so(); } printf("Case %d: %d\n",zu,ans-tmp); } return 0; }
相关文章推荐
- 【费用流模型】BZOJ2668 UVA1317 UVA1486 UVA1104
- 【费用流】hdu1533 poj2516 bzoj1070 bzoj1061
- [网络流24题 #16]数字梯形问题
- [网络流24题 #18]分配问题
- [网络流24题 #18]分配问题
- 收益最大
- POJ2175 费用流消负圈
- poj 3422 费用流
- UVA 10806 Dijkstra, Dijkstra.(最小费用最大流)
- 【BeiJing wc2012】【BZOJ2661】连连看
- 【SCOI2007】【BZOJ1070】修车
- 【NOI2008】【BZOJ1061】志愿者招募
- 【SDOI2013】【BZOJ3197】assassin
- 【SDOI2009】【BZOJ1877】晨跑
- HDU 4807 Lunch Time
- NOI 2008 志愿者招募
- HDU 4406 GPA 最大费用流
- HDU 4411 Arrest 最小费用流
- HDU 1533 Going Home 最小费用流
- HDU 3488 Tour 费用流