zoukankan      html  css  js  c++  java
  • 【题解】航空路线问题

    航空路线问题

    一个点有两种用法,但是只能选一种用,直接把一个点拆掉并且连一条容量为1的边就成功限制。

    将一个点拆为两个点,一个入点一个出点,入点到出点连一条费用为(-inf) 的边,跑费用流,最终答案就是

    [-dfrac {cost} {inf} ]

    输出方案随便弄一下就好了。注意考虑边界情况!!!(1-》n),(不连通)

    强行总结:将一个状态点拆成两个点,中间用一条边来限制,可以模拟一个一个点只有两种状态的图,更多状态甚至都可以。

    费用流不能跑负环。spfa能跑什么费用流就可以跑什么。

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<vector>
    
    
    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;
    }
    struct E{
          int to,nx,w,c;
          E(){to=nx=w=c=0;}
          E(const int&a,const int&b,const int&CX,const int&d){to=a;nx=b;w=CX;c=d;}
    }e[30005];
    int head[404];
    int cnt=1;
    inline void add(const int&fr,const int&to,const int&w,const int&c,const bool&f){
          e[++cnt]=E(to,head[fr],w,c);
          head[fr]=cnt;
          //printf("fr=%d to=%d w=%d c=%d cnt=%d
    ",fr,to,w,c,cnt);
          if(f)add(to,fr,0,-c,0);
    }
    const int maxn=505;
    int d[maxn];
    int fl[maxn];
    int in[maxn];
    int last[maxn];
    
    int S,T,n,v,cost;
    const int inf=0x3f3f3f3;
    const int littleinf=1;
    
    queue < int > q;
    void mincost(){
          
          while(1){
    	    for(register int t=1;t<=T;++t) d[t]=inf,fl[t]=0,last[t]=0,in[t]=0;
    	    d[S]=0;fl[S]=inf;
    	    q.push(S);
    	    while(!q.empty()){
    		  register int now=q.front();
    		  q.pop();
    		  in[now]=0;
    		  //cout<<now<<endl;
    		  for(register int t=head[now];t;t=e[t].nx){
    			//cout<<t<<endl;
    			if(d[e[t].to]>e[t].c+d[now]&&e[t].w>0){
    			      d[e[t].to]=e[t].c+d[now];
    			      if(!in[e[t].to]) q.push(e[t].to);
    			      in[e[t].to]=1;
    			      fl[e[t].to]=min(e[t].w,fl[now]);
    			      last[e[t].to]=t;
    			}
    		  }
    	    }
    	    if(fl[T]<=0)return;
    	    cost-=fl[T]*d[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];
          }
    }
    
    vector < int > ve,VE;
    map < string , int > name;
    map < int , string > arc;
    int main(){	    
          freopen("airl.in","r",stdin);
          freopen("airl.out","w",stdout);
          n=qr();v=qr();
          for(register int t=1;t<=n;++t){
    	    string f;
    	    cin>>f;
    	    name[f]=t;
    	    arc[t]=f;
    	    add(t+1,t+n+1,1+(t==1||t==n),0,1);
          }
          
          for(register int t=1;t<=v;++t){
    	    string t1,t2;
    	    cin>>t1>>t2;
    	    int i1,i2;
    	    i1=name[t1];i2=name[t2];
    	    if(i1>i2)swap(i1,i2);
    	    add(i1+n+1,i2+1,1+(i1==1&&i2==n),-1,1);
          }
          
          S=1;
          T=n+n+2;
          add(n+n+1,T,2,0,1);
          add(S,2,2,0,1);
          mincost();
          if(e[cnt].w!=2) return puts("No Solution!"),0;
          printf("%d
    ",cost);
          int now=1;
          ve.push_back(now);
          while(now!=n){
    	    for(register int t=head[now+n+1];t;t=e[t].nx){
    		  if(e[t^1].w&&e[t].to>1&&e[t].to<=n+1&&!in[e[t].to-1]){
    			now=e[t].to-1;
    			break;
    		  }
    	    }
    	    in[now]=1;
    	    ve.push_back(now);
          }
          in[n]=0;
          now=1;
          while(now!=n){
    	    int f=1;
    	    for(register int t=head[now+n+1];t;t=e[t].nx){
    		  if(e[t^1].w&&e[t].to>1&&e[t].to<=n+1&&!in[e[t].to-1]){
    			now=e[t].to-1;
    			f=0;
    			break;
    		  }
    	    }
    	    if(now==n||f)break;
    	    in[now]=1;
    	    VE.push_back(now);
          }
          reverse(VE.begin(),VE.end());
          VE.push_back(1);
          
          for(vector< int >::iterator t=ve.begin();t!=ve.end();++t) cout<<arc[*t]<<endl;
          for(vector< int >::iterator t=VE.begin();t!=VE.end();++t) cout<<arc[*t]<<endl;
          return 0;
    }
    
    
  • 相关阅读:
    Shell for
    rsync 目录 斜杠
    shell local
    linux secureCRT utf-8编码显示
    eclipse maven 项目不显示 target目录
    如何打印身份证实际大小
    linux 去掉 ^M
    hibernate 之 集合映射中list映射
    hibernate 之 复合主键映射
    hibernate 之 组件映射
  • 原文地址:https://www.cnblogs.com/winlere/p/11234628.html
Copyright © 2011-2022 走看看