魔法王国
【问题描述】
从古代开始,魔法王国就有一个由双向魔法门构成的网络。每一个魔法门以魔法连接一对城市,允许他们进行魔法交流和旅行。被魔法门连接起来的城市被称为相邻的。
Albert王子和Betty公主住在相邻的城市。所以,在他们的孩提时代,Albert和Betty经常通过魔法通讯球保持联系,魔法通讯球是通过连接城市的魔法门工作的。
Albert和Betty相爱了。他们爱得如此深以至不能在没有对方时生活一分钟。他们总是把魔法球带在身边,从而,他们可以在任何时候与对方说话。他们的爱情有一个奇怪的事情——他们从没见过对方,甚至他们害怕同时在同一个城市。人们说,是魔法球影响了他们。
对于Albert和Betty来说,在王国里旅行是一件复杂的事情。他们必须通过魔法门旅行,这对于皇家而言也是非常昂贵的。他们可以同时使用不同的魔法门移动到不同的城市,也可以一方使用魔法门移动到一个城市,另一方呆在一个城市。在任何时候他们必须在相邻的城市。他们不能同时使用同一个魔法门移动。
须找到一个最便宜的方案——他们通过魔法门移动的次数最少。如果他们同时使用魔法门,计做两次移动。
【输入格式】
输入文件的第一行包含整数n,m,a1,b1,a2,b2。这里n(3 <= n <=100)是王国里的城市数(城市从1到n标号);m(2 <= m <= 1000)是魔法门的个数;是相邻的城市,对应的分别是Albert和Betty的出发城市;也是相邻的城市,对应的分别是Albert和Betty希望到达的城市。
接下来的m行描述魔法门。每一行包含两个数pi1和pi2——用魔法门相连的城市。任意两个城市之间最多只有一个魔法门连接。
【输出格式】
输出文件的第一行包含两个用一个空格隔开的整数c。这里c是方案中最少的移动次数;
【输入样例】KINGDOM.IN
4 5 1 2 2 1
1 2
2 3
3 4
4 1
1 3
【输出样例】KINGDOM.OUT
3
【分析】
大家看完题目,就会发现这是一道最短路问题。但是,题目中最短路的起点和终点是一对城市,而且他们在旅行的过程中,两人也必须在相邻的城市。如果直接跑一遍最短路是肯定不行的。仔细分析题目,发现他们经过的城市都是相邻的。这样我们可以把每对相邻的城市都看作一个点,这样共有2m个点。接下来要确定每两点之间的距离,有3种情况:
1. 这两对相邻城市中,第一个城市相同,第二个城市联通,边权为1;
2. 这两对相邻城市中,第二个城市相同,第一个城市联通,边权为1;
3. 这两对相邻城市中,两个城市都联通,边权为2;
做完这些之后,跑一遍最短路即可。
本人略丑的代码<-_->
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#define For(c,a,b) for(int c=a;c<=b;c++)
#define foR(c,a,b) for(int c=a;c>=b;c--)
using namespace std;
const int N=405;
int n,m,a1,a2,b1,b2,x[N],y[N];
int f[N][N],g[N][N],tot;
int main()
{
freopen("kingdom.in","r",stdin);
freopen("kingdom.out","w",stdout);
scanf("%d%d%d%d%d%d",&n,&m,&a1,&a2,&b1,&b2);
For(i,1,m)
{
int u,v;
scanf("%d%d",&u,&v);
g[u][v]=++tot; x[tot]=u; y[tot]=v;
g[v][u]=++tot; x[tot]=v; y[tot]=u;
}
memset(f,0x3f,sizeof(f));
For(i,1,tot-1) For(j,i+1,tot)
{
if (x[i]==x[j]&&g[y[i]][y[j]]) f[i][j]=1;
else if (y[i]==y[j]&&g[x[i]][x[j]]) f[i][j]=1;
else if (g[x[i]][x[j]]&&g[y[i]][y[j]]
&&(x[i]!=y[j]||x[j]!=y[i])) f[i][j]=2;
f[j][i]=f[i][j];
}
For(k,1,tot) For(i,1,tot)
if (k!=i) For(j,1,tot)
if (k!=j&&i!=j)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
//Floyed可能会超时,可能是数据水
//建议用时间复杂度低于O(m^2)的算法
printf("%d\n",f[g[a1][a2]][g[b1][b2]]);
fclose(stdin); fclose(stdout);
return 0;
}