题目描述:
你赢得了一场航空公司举办的比赛,奖品是一张加拿大环游机票。旅行在这家航空公司开放的最西边的城市开始,然后一直自西向东旅行,直到你到达最东边的城市,再由东向西返回,直到你回到开始的城市。除了旅行开始的城市之外,每个城市只能访问一次,因为开始的城市必定要被访问两次(在旅行的开始和结束)。
当然不允许使用其他公司的航线或者用其他的交通工具。
给出这个航空公司开放的城市的列表,和两两城市之间的直达航线列表。找出能够访问尽可能多的城市的路线,这条路线必须满足上述条件,也就是从列表中的第一个城市开始旅行,访问到列表中最后一个城市之后再返回第一个城市。
输入输出格式
输入格式:
第 1 行: 航空公司开放的城市数 N 和将要列出的直达航线的数量 V。N 是一个不大于 100 的正整数。V 是任意的正整数。
第 2..N+1 行: 每行包括一个航空公司开放的城市名称。城市名称按照自西向东排列。不会出现两个城市在同一条经线上的情况。每个城市的名称都 是一个字符串,最多15字节,由拉丁字母表上的字母组成;城市名称中没有空格。
第 N+2..N+2+V-1 行: 每行包括两个城市名称(由上面列表中的城市名称组成),用一个空格分开。这样就表示两个城市之间的直达双程航线。
输出格式:
Line 1: 按照最佳路线访问的不同城市的数量 M。如果无法找到路线,输出 1。
输入输出样例
输入样例#1:
8 9
Vancouver
Yellowknife
Edmonton
Calgary
Winnipeg
Toronto
Montreal
Halifax
Vancouver Edmonton
Vancouver Calgary
Calgary Winnipeg
Winnipeg Toronto
Toronto Halifax
Montreal Halifax
Edmonton Montreal
Edmonton Yellowknife
Edmonton Calgary
输出样例#1:
7
题目大意:
给定一个无向图,让你从1走到n再走回来,除1之外每个点只能经过一次,求经过的最大点数。
解题思路:
1.首先,对输入进行处理,把输入的字符串转化成点,使用“map”:传送门。
2.我们可以转化一下,从一走到n再回到1,可以等效为,两个人一起从1出发,一个人走到n,另一个人走到一个和n直接相连的点。
题解:
附在了代码后面(习惯了~~~)
代码(c++)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<map> 7 using namespace std; 8 int n,m,f[101][101],v[5001][5001];/*f[i][j]表示第一人走到i,第二人走到j时经过的城市数*/ 9 string s[101]; 10 map<string,int>b; 11 int main() 12 { 13 cin>>n>>m; 14 for(int i=1;i<=n;i++){ 15 cin>>s[i]; b[s[i]]=i; 16 }/*将第i个字符串映射为i*/ 17 for(int i=1;i<=m;i++){ 18 string l,r; cin>>l>>r; 19 v[b[l]][b[r]]=1; v[b[r]][b[l]]=1; 20 }/*两点之间有路就变为1*/ 21 f[1][1]=1;/*初始化*/ 22 for(int i=1;i<=n;i++) 23 for(int j=i+1;j<=n;j++) 24 for(int k=1;k<j;k++){/*这3重循环和Floyed好像啊~~~~~*/ 25 if(v[k][j]&&f[i][k])/*如果k和j之间有道路,并且第一人到i,第二人到k这种情况是存在的,才可以转移*/ 26 f[i][j]=max(f[i][k]+1,f[i][j]);/*很简单的方程*/ 27 f[j][i]=f[i][j];/*第一人走到i,第二人走到j和第一人走到j,第二人走到i是等效的.*/ 28 } 29 int ans=1;/*至少经过一个城市,就是起始城市*/ 30 for(int i=1;i<=n;i++) 31 if(v[i][n])/*这个必须要加的,我们更新的是f[i][n],看下面↓↓↓,f[i][n]指的是: 1). 从1走到n(中间经过某些城市); 2).再从n直接走到i; 3). 然后从i经过某些道路走回1.基于第二点我们要保证n和i之间要有道路*/ 32 ans=max(ans,f[i][n]); 33 cout<<ans; 34 return 0; 35 }
完~~~~~~~