【题解】数字梯形问题

【题解】数字梯形问题

这样一道傻题我调了这么久

三个任务建图是这样的,由于太简单就不xjb解释了,一个点拆位入点和出点

graph LR S==w=1,c=1==>入点1 入点1 --w=1,c=点权1--> 出点1 入点2 --w=1,c=点权2--> 出点2 入点3 --w=1,c=点权2--> 出点3 出点1 --w=1,c=0--> 入点2 出点1 --w=1,c=0--> 入点3 出点2 ==w=1==>T 出点3 ==w=1==>T
graph LR S==w=1,c=1==>入点1 入点1 --w=2,c=点权1--> 出点1 入点2 --w=2,c=点权2--> 出点2 入点3 --w=2,c=点权2--> 出点3 出点1 --w=1,c=0--> 入点2 出点1 --w=1,c=0--> 入点3 出点2 ==w=inf==>T 出点3 ==w=inf==>T
graph LR S==w=1,c=1==>入点1 入点1 --w=inf,c=点权1--> 出点1 入点2 --w=inf,c=点权2--> 出点2 入点3 --w=inf,c=点权2--> 出点3 出点1 --w=inf,c=0--> 入点2 出点1 --w=inf,c=0--> 入点3 出点2 ==w=inf==>T 出点3 ==w=inf==>T

一次加边即可,不过由于是费用流所以貌似要重置残余网络

注意数组大小和边界!好坑。

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>

using namespace std;  typedef long long ll;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(c<48||c>57)f|=c==45,c=getchar();
      while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;
}
const int maxn=1e3+5;
struct E{
      int to,nx,w,c;
      E(){to=nx=c=w=0;}
      E(const int&a,const int&b,const int&C,const int&d){to=a;nx=b;w=C;c=d;}
      inline void print(){
	    printf("to=%d nx=%d w=%d c=%d\n",to,nx,w,c);
      }
}e[maxn*maxn<<3];
int head[maxn*15];
int cnt=1;
int data[55][55];
int id[55][55];
int nodecnt;
int S,T;
int n,m;
int ts,tt;

inline void add(const int&fr,const int&to,const int&w,const int&c,const int&f=1){
      //if(cnt>=(maxn*maxn<<3)) puts("WA"),exit(1);
      //      printf("%d %d %d %d %d\n",fr,to,w,c,f);
      e[++cnt]=E(to,head[fr],w,c);
      head[fr]=cnt;
      if(f)add(to,fr,0,-c,0);	    
}


queue < int > q;
const int inf=0x3f3f3f3f;
int in[maxn*15];
int fl[maxn*15];
int last[maxn*15];
int d[maxn*15];
inline int mincost(){
      int ret=0;
      while(1){
	    for(register int t=1;t<=nodecnt;++t) d[t]=inf,fl[t]=0,in[t]=0;
	    d[S]=0;q.push(S);fl[S]=inf;
	    while(q.size()){
		  register int now=q.front();
		  q.pop();
		  in[now]=0;
		  //cout<<"now="<<now<<' '<<T<<endl;
		  for(register int t=head[now];t;t=e[t].nx){
			if(d[e[t].to]>d[now]+e[t].c&&e[t].w>0){
			      d[e[t].to]=d[now]+e[t].c;
			      fl[e[t].to]=min(e[t].w,fl[now]);
			      last[e[t].to]=t;
			      if(!in[e[t].to]) q.push(e[t].to);
			      in[e[t].to]=1;
			}
		  }
	    }
	    
	    //cout<<"fl[T]="<<fl[T]<<endl;
	    if(fl[T]==0)break;
	    ret+=d[T]*fl[T];
	    for(register int t=T;t!=S;t=e[last[t]^1].to)
		  e[last[t]].w-=fl[T],e[last[t]^1].w+=fl[T];
      }
      return ret;
}


inline void reset(){
      for(register int t=2;t<=cnt;t+=2){
	    e[t].w+=e[t+1].w;
	    e[t+1].w=0;
	    //e[t].print();
	    //e[t+1].print();
	    
      }
}

int main(){
                  
      m=qr();n=qr();
      for(register int t=1;t<=n;++t)
	    for(register int i=1;i<=m+t-1;++i){
		  data[t][i]=-qr(),id[t][i]=++nodecnt,add(id[t][i],++nodecnt,1,data[t][i]);
		  //cout<<data[t][i]<<' ';
	    }
      S=++nodecnt;
      T=++nodecnt;
      
      for(register int t=1;t<=n;++t){
	    for(register int i=1;i<=m+t-1;++i){
		  if(id[t+1][i+1]) add(id[t][i]+1,id[t+1][i+1],1,0);
		  if(id[t+1][i]) add(id[t][i]+1,id[t+1][i],1,0);
		  //cout<<" qaq="<<id[t][i]<<' '<<id[t+1][i+1]<<' '<<id[t+1][i]<<' ';
	    }
      }
      

      int ans1,ans2,ans3;
      ts=++nodecnt;
      add(S,ts,m,0);
      for(register int t=1;t<=m;++t) {
	    add(ts,id[1][t],1,0);
	    //cout<<"to=s "<<ts<<' '<<id[1][t]<<' ';
      }
      //cout<<endl;
      for(register int t=1;t<=m+n-1;++t) {
	    add(id[n][t]+1,T,inf,0);
	    //cout<<"id="<<id[n][t]<<' '<<endl;
      }

      
      ans1=mincost();
      reset();
      //cout<<ans1<<endl;
      //return 0;

      for(register int t=1;t<=n;++t)
	    for(register int i=1;i<=m+t-1;++i)
		  add(id[t][i],id[t][i]+1,inf,data[t][i]);
      
      
      ans2=mincost();
      reset();

      for(register int t=1;t<=n;++t){
	    for(register int i=1;i<=m+t-1;++i){
		  if(id[t+1][i+1]) add(id[t][i]+1,id[t+1][i+1],inf,0);
		  if(id[t+1][i]) add(id[t][i]+1,id[t+1][i],inf,0);
	    }
      }
      
      ans3=mincost();
      printf("%d\n%d\n%d\n",-ans1,-ans2,-ans3);
      
      return 0;
}

猜你喜欢

转载自www.cnblogs.com/winlere/p/11239536.html