NKOI 1946 航空路线

来源:互联网 发布:淘宝直通车一天烧50万 编辑:程序博客网 时间:2024/05/01 09:14

【线性规划与网络流24题 11】航空路线

Time Limit:10000MS  Memory Limit:65536K
Total Submit:18 Accepted:2 
Case Time Limit:1000MS

Description

给定一张航空图,图中顶点代表城市,边代表2城市间的直通航线。现要求找出一条满足下述限制条件的且途经城市最多的旅行路线。 
(1)从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然后再单向从东向西飞回起点(可途经若干城市)。 
(2)除起点城市外,任何城市只能访问1次。 

编程任务: 
对于给定的航空图,试设计一个算法找出一条满足要求的最佳航空旅行路线。 

由于本OJ无Special Judge , 所以只需要输出最多经过的城市数

Input

第1 行有2个正整数N 和V,N 表示城市数,N<100,V 表示直飞航线数。 
接下来的N行中每一行是一个城市名,可乘飞机访问这些城市。 
城市名出现的顺序是从西向东。也就是说,设i,j 是城市表列中城市出现的顺序,当i>j 时,表示城市i 在城市j 的东边,而且不会有2 个城市在同一条经线上。城市名是一个长度不超过15 的字符串,串中的字符可以是字母或阿拉伯数字。例如,AGR34或BEL4。 
再接下来的V 行中,每行有2 个城市名,中间用空格隔开,如 city1 city2 表示city1到city2 有一条直通航线,从city2 到city1 也有一条直通航线。

Output

一行,包含一个整数或字符串,表示最多经过的城市数,如果无解,则输出"No Solution!"(不包含引号)

Sample Input

8 9VancouverYellowknifeEdmontonCalgaryWinnipegTorontoMontrealHalifaxVancouver EdmontonVancouver CalgaryCalgary WinnipegWinnipeg TorontoToronto HalifaxMontreal HalifaxEdmonton MontrealEdmonton YellowknifeEdmonton Calgary

Sample Output

7

Source

感谢 Wo_ai_WangYuan 修改题目并放上数据


这题要用到最大费用最大流

把问题抽象成图论问题,数学模型是求从S到T的两条不相交的路径,使得路径上点的权值之和最大。
费用流建模,首先拆点,把顶点x拆成x和x',x 与x'之间连接一条费用为1,容量为1的有向边;  

特殊地,1和n两个节点拆分后点内边容量设为2

对于与x相连的点a(a>x)x'向a连一条费用为0,容量为1的边。

最后再特判一下无解的情况

#include<cstdio>#include<iostream>#include<cstring>#include<map> #include<vector>#include<queue>using namespace std;const int maxn=505,inf=1e9;string ss,tt;int n,m,last[maxn],path[maxn],op,ed;int dis[maxn],vd[maxn],maxflow,mincost;bool flag[maxn];map<string,int>id;struct wr{       int a,b,c,w,NEXT;    wr(int a,int b,int w,int c,int NEXT):a(a),b(b),w(w),c(c),NEXT(NEXT){}   };   vector<wr>s;   void insert(int a,int b,int w,int c){      s.push_back(wr(a,b,w,c,last[a]));       last[a]=s.size()-1;       s.push_back(wr(b,a,-w,0,last[b]));       last[b]=s.size()-1;   }   struct wk{             int  n;                  void init(int n){           this->n =n;           memset(last,-1,sizeof(last));       }                                bool find(int st,int nd){                 int i;          queue<int>q;                 for(i=1;i<=n;i++)dis[i]=-inf,path[i]=-1;           dis[st]=0,path[st]=0,flag[st]=1;             q.push(st);                 while(!q.empty()){                     int x=q.front();                     q.pop();flag[x]=0;                 for(i=last[x];i!=-1;i=s[i].NEXT){                      wr& e=s[i];                           if(e.c>0&&dis[x]+e.w>dis[e.b]){                             dis[e.b]=dis[x]+e.w;                       path[e.b]=i;                             if(!flag[e.b]){                                 q.push(e.b) ;                                 flag[e.b]=1;                             }                         }                      }                 }             return dis[nd]>-inf;               }         }spfa;     void addflow(){       int flow=inf,i;       for(i=ed;i!=op&&s[path[i]].a!=0;i=s[path[i]].a)           flow=min(flow,s[path[i]].c);       maxflow+=flow;       mincost+=dis[ed]*flow;       for(i=ed;i!=op;i=s[path[i]].a){           int x=path[i];           s[x].c-=flow;           s[x^1].c+=flow;       }   }        int main(){cin>>n>>m;int i,j;op=1,ed=2*n;spfa.init(ed);for(i=1;i<=n;i++){cin>>ss;id[ss]=i;if(i==1||i==n)insert(i,i+n,1,2);else insert(i,i+n,1,1);}for(i=1;i<=m;i++){cin>>ss>>tt;int id1=id[ss],id2=id[tt];if(id1>id2)swap(id1,id2);insert(id1+n,id2,0,1);}while(spfa.find(op,ed))addflow();       if(maxflow==1&&mincost==2) printf("2");    else if(maxflow!=2)printf("No Solution!");    else printf("%d",mincost-2);} 


0 0