zoukankan      html  css  js  c++  java
  • 【题解】数字梯形问题

    【题解】数字梯形问题

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

    三个任务建图是这样的,由于太简单就不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
    ",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
    ",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
    %d
    %d
    ",-ans1,-ans2,-ans3);
          
          return 0;
    }
    
    
  • 相关阅读:
    margin塌陷(collapse)
    this的值
    变量、函数声明提升
    Git与Svn的区别—笔记1
    ECMAScript 总结
    正则表达式
    i2c 通信
    player/stage 学习---安装
    各种分区类型对应的partition_Id
    ubuntu 映射网络驱动器到本地
  • 原文地址:https://www.cnblogs.com/winlere/p/11239536.html
Copyright © 2011-2022 走看看