[上下界费用流] BZOJ2055. 80人环游世界

来源:互联网 发布:excel表格筛选重复数据 编辑:程序博客网 时间:2024/04/28 04:12

又一道模板题

按题意建图,就是一个上下界的网络流了

M个人的限制,只要把tt到ss的边上流量设为M就行了

#include <cstdio>#include <iostream>#include <algorithm>#include <queue>using namespace std;const int N=510,inf=1<<30;int S,T,ss,tt,n,m,cnt=1,v[N],G[N];struct edge{  int t,nx,f,w;}E[N*N*10];inline void link(int x,int y,int f,int w){  E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt; E[cnt].f=f; E[cnt].w=w;  E[++cnt].t=x; E[cnt].nx=G[y]; G[y]=cnt; E[cnt].f=0; E[cnt].w=-w;}queue<int> Q;int dis[N],vis[N],frm[N];int ans;inline bool spfa(){  for(int i=1;i<=T;i++) dis[i]=inf,vis[i]=0;  vis[S]=1; Q.push(S); dis[S]=0;  while(!Q.empty()){    int x=Q.front(); vis[x]=0; Q.pop();    for(int i=G[x];i;i=E[i].nx)      if(E[i].f && dis[E[i].t]>dis[x]+E[i].w){    dis[E[i].t]=dis[x]+E[i].w; frm[E[i].t]=i;    if(!vis[E[i].t])      vis[E[i].t]=1,Q.push(E[i].t);      }  }  if(dis[T]==inf) return false;  int mf=inf;  for(int i=T;i!=S;i=E[frm[i]^1].t) mf=min(mf,E[frm[i]].f);  ans+=mf*dis[T];  for(int i=T;i!=S;i=E[frm[i]^1].t) E[frm[i]].f-=mf,E[frm[i]^1].f+=mf;  return true;}int main(){  freopen("1.in","r",stdin);  freopen("1.out","w",stdout);  scanf("%d%d",&n,&m);  ss=n+n+1; tt=ss+1; S=tt+1; T=S+1;  for(int i=1;i<=n;i++){    scanf("%d",&v[i]);    link(S,i+n,v[i],0); link(i,T,v[i],0);    link(ss,i,inf,0); link(i+n,tt,inf,0);  }  for(int i=1;i<n;i++)    for(int j=1,x;j<=n-i;j++){      scanf("%d",&x);      if(~x) link(i+n,i+j,inf,x);    }  link(tt,ss,m,0);  while(spfa());  printf("%d\n",ans);  return 0;}
原创粉丝点击