HDU 4460
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4460
题意:
一些点(<=1e3)一些边(<=1e5)。问任意两点最大距离多少。若不联通输出-1.
思路:
原来spfa一直搞错了,用优先队列的叫dij,不用的叫spfa……有时候加优先队列还会慢,因为有个O(logn)的复杂度在那里,而且一个点因为不同的距离值会入队多次,所以不能最短路总是上优先队列。
复现的时候算了下复杂度,总觉得O(M)才是比较靠谱的,感觉这样单纯暴力枚举是过不了的,于是往连通性方面搞了下,两个小时后就弃题了……
实际上,可能是数据水,纯spfa也是能过的……也是脑卡,都成全场题了为什么不试一发……spfa的复杂度用BELLMAN-FORD的复杂度去考虑,最差O(n^2),最好O(n)。
源码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
#include <map>
using namespace std;
const int MAXN = 1000 + 5;
#define inf (1000000007)
int d[MAXN];
struct D
{
int u, d;
bool operator < (const D&rbs)const{
return d < rbs.d;
}
};
vector<int>lin[MAXN];
queue<int>que;
char s1[MAXN], s2[MAXN];
map<string, int>mm;
int ans;
int vis[MAXN];
int n, m;
void bfs(int u)
{
// printf("org u = %d\n", u);
for(int i = 1 ; i <= n ; i++)
d[i] = inf, vis[i] = 0;
while(!que.empty()) que.pop();
vis[u] = 1, d[u] = 0, que.push(u);
while(!que.empty()){
u = que.front(); que.pop();
// printf("u = %d\n", u);
vis[u] = 0;
for(int j = 0 ; j < (int)lin[u].size() ; j++){
int v = lin[u][j];
if(d[v] > d[u] + 1){
// printf("v = %d\n", v);
d[v] = d[u] + 1;
if(vis[v] == 0) que.push(v), vis[v] = 1;
}
}
}
// for(int i = 1 ; i <= n ; i++) printf("d[%d] = %d\n", i, d[i]);
for(int i = 1 ; i <= n ; i++)
ans = max(ans, d[i]);
}
int main()
{
// freopen("HDU 4460.in", "r", stdin);
while(scanf("%d", &n) != EOF && n){
mm.clear();
for(int i = 1 ; i <= n ; i++){
scanf("%s", s1);
mm[s1] = i;
lin[i].clear();
}
scanf("%d", &m);
for(int i = 1 ; i <= m ; i++){
scanf("%s%s", s1, s2);
// printf("first = %d, second = %d\n", mm[s1], mm[s2]);
lin[mm[s1]].push_back(mm[s2]);
lin[mm[s2]].push_back(mm[s1]);
}
ans = 0;
for(int i = 1 ; i <= n ; i++)
bfs(i);
if(ans == inf) printf("-1\n");
else printf("%d\n", ans);
}
return 0;
}