题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4460
题意:求任意两点间最短路,输出这些最短路中的最长距离。为了不超时,进行n次bfs取最大值即可。详解请见代码。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<map>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 10000 + 5;
const int INF = 0x3f3f3f3f;
vector<int>vt[maxn];
int vis[maxn];
int dis[maxn];
int t;
int solve(int cur)//bfs
{
int ans = 0;
memset(vis, 0, sizeof(vis));//注意清空
for(int i = 1; i <= t; i++) dis[i] = -INF;//is数组用于储存当前点cur到各点之间的距离,初始化为无穷大
queue<int> q;
while(!q.empty()) q.pop();
q.push(cur);
vis[cur] = 1;//标记改点是否加入过vector中
dis[cur] = 0;//cur到cur自身的距离为0
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i = 0; i < vt[u].size(); i++)//依次取出与当前点u相连的各点记为v
{
int v = vt[u][i];
if(!vis[v] && dis[v] < dis[u] + 1)//v为加入过集合中并且u到v的距离小于u+1
{
dis[v] = dis[u] + 1;
q.push(v);//将v加入集合
vis[v] = 1;//标记
}
}
}
for(int i = 1; i <= t; i++)
{
if(dis[i] == -INF) return -1;//如果点cur有不能到达的点,返回-1
ans = max(ans, dis[i]);
}
return ans;//否则返回点cur到各点最短路中的最长距离
}
int main()
{
while(~scanf("%d",&t) && t)
{
map<string, int> mp;//用于给名字编号
for(int i = 0; i <= t; i++)
vt[i].clear();//注意清空初始化
char ch[15];
for(int i = 1; i <= t; i++)
{
scanf("%s",&ch);
mp[(string)ch] = i;//编号
}
int m;
scanf("%d",&m);
while(m--)
{
char ch1[15],ch2[15];
scanf("%s%s",ch1,ch2);
int u = mp[(string)ch1], v = mp[(string)ch2];
vt[u].push_back(v);//建立每条边两端点之间的联系
vt[v].push_back(u);
}
int sum = 0;
int vis = 0;
for(int i = 1; i <= t; i++)//进行n次bfs,每次求点i到各点之间的距离的最大值
{
int num = solve(i);
if(num == -1)//若点i有不能到达的点,返回-1,
{
vis = 1; break;
}
else
sum = max(sum, num);//求任意两点间最短路中的最长长度
}
if(vis == 0)
printf("%d\n",sum);//输出这个最短路中的最长长度
else
printf("-1\n");
}
return 0;
}