换句话解释题意就是说求最短路的最大值(相邻两点的距离为1),数据范围是点数 1000 ,边数20000, 难道要求所有点之间的最短路再求最大值, O(n^3) 有点大。
怎么办呢? 其实是可以优化的,从一个源点用BFS一圈一圈地向外扩展,最短路即圈数,复杂度是O(n),比dijkstra或SPFA都要好,其次,如果图不是联通的,那么答案肯定的INF,直接输出。 这样整体最坏情况是O(n^2) ,能AC.
如果数据是随机生成的,这题采用随机化是个不错的选择。 试了试,还真的通过了,限制5次都过了,这数据还真水的可以。。时间骤降到十几分之一。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <algorithm>
#include <map>
#include <ctime>
using namespace std;
const int maxn=1010,maxe=20050,INF=100000000;
int N,M,e,Mpn;
int head[maxn],next[maxe],to[maxe];
map<string,int> MP;
void Init()
{
MP.clear();
memset(head,0,(N+1)*sizeof(int));
e=Mpn=1;
}
void add_edge(int u,int v){
next[e]=head[u] , to[e]=v , head[u] = e++;
}
int d[maxn];
int BFS(int st){
memset(d,-1,(N+1)*sizeof(int));
queue<int> Q;
Q.push(st) , d[st]=0;
int cnt=1 , M=0;
while(!Q.empty()){
int u=Q.front(); Q.pop();
for(int i=head[u] ; i ;i=next[i]){
int v=to[i];
if(d[v]!=-1 || v==u) continue;
d[v] = d[u]+1 , Q.push(v) ,M=max(M , d[v]) , cnt++;
}
}
return cnt==N ? M : INF;
}
char word[100],word2[100];
int main()
{
srand(time(0));
while(scanf("%d",&N) && N){
Init();
for(int i=1;i<=N;i++){
scanf("%s",word) , MP[(string)word]=i;
}
scanf("%d",&M);
for(int i=1;i<=M;i++){
scanf("%s%s",word,word2);
int a=MP[(string)word] , b=MP[(string)word2];
add_edge(a,b) , add_edge(b,a);
}
int ans=0;
int steps=min(N,100);
for(int i=1;i<=steps && ans!=INF ;i++){
int tt=rand()%N+1;
ans = max(ans,BFS(tt));
}
if(ans==INF) printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}