传送门
// 题意: 给定一个无向图(n, m),在给定一个起点和终点, 问地点和终点中可能路径中的最大的那条边的权值是多少.
// 思路: 这个问题还是比较经典, 很多题都要这个问题, 那么我们看这个数据范围, 200,可以跑floyd, 得出任意两点之间的距离的最大的边, 就是对floyd进行一些小的膜改. 首先初始化矩阵是我们应该同一点初始化为inf, 不同点初始化为0, 然后0代表不能到达, 所以floyd中关键语句为:
if (g[i][k] && g[k][j])
g[i][j] = max(g[i][j], min(g[i][k], g[k][j]));
然后就可以通过此题了.
AC Code
const int maxn = 2e2+5;
int cas=1;
int g[maxn][maxn];
map<string, int>mp;
int n, m;
void floyd() {
for (int k = 1 ; k <= n ; k ++) {
for (int i = 1 ; i <= n ; i ++) {
for (int j = 1 ; j <= n ; j ++) {
if (g[i][k] && g[k][j])
g[i][j] = max(g[i][j], min(g[i][k], g[k][j]));
}
}
}
}
void solve()
{
while(cin >> n >> m ) {
if (n + m == 0) break;
for (int i = 1 ; i <= n ; i ++) {
for (int j = 1 ; j <= n ; j ++) {
if (i == j) g[i][j] = inf;
else g[i][j] = 0;
}
}
Fill(g, 0);
int cnt = 0; mp.clear();
for (int i = 1 ; i <= m ; i ++) {
string s1, s2; int w;
cin >> s1 >> s2 >> w;
if (!mp[s1]) mp[s1] = ++cnt;
if (!mp[s2]) mp[s2] = ++cnt;
g[mp[s1]][mp[s2]] = g[mp[s2]][mp[s1]] = w;
}
floyd();
string s1, s2;
cin >> s1 >> s2;
int s = mp[s1]; int t = mp[s2];
printf("Scenario #%d\n", cas++);
if (s != t) cout << g[s][t] << " tons" << endl << endl;
else cout << 0 << " tons" << endl << endl;
}
}
那我们想一想如果数据量比较大了? 当然dij也能过. 但是我要说一种比dij简单一点的方法, 也就是并查集.
我们首先将边的信息按从大到小排一个序, 然后贪心的从大的开始选, 并把他们并在一起, 如果某次并的过程中发现我们要对源点 和 汇点 并在一起了, 我们此时的边权也就是我们的ans. 这个方法就很好啦~.
AC Code(并查集)
const int maxn = 2e2+5;
int cas=1;
struct node {
int u, v, w;
bool operator < (const node & a) const {
return w > a.w;
}
}e[maxn*maxn];
int fa[maxn];
int Find(int x) {
return fa[x] == x ? x : fa[x] = Find(fa[x]);
}
void solve()
{
int n, m;
while(cin >> n >> m) {
if (n + m == 0) break;
map<string, int>mp; int cnt = 0;
for (int i = 1 ; i <= n ; i ++) fa[i] = i;
for (int i = 1 ; i <= m ; i ++) {
string s1, s2; int w;
cin >> s1 >> s2 >> w;
if (!mp[s1]) mp[s1] = ++cnt;
if (!mp[s2]) mp[s2] = ++cnt;
e[i].u = mp[s1]; e[i].v = mp[s2];
e[i].w = w;
}
sort(e+1, e+1+m);
string s1, s2;
cin >> s1 >> s2;
int s = mp[s1]; int t = mp[s2];
int ans = 0;
for (int i = 1 ; i <= m ; i ++) {
int u = Find(e[i].u);
int v = Find(e[i].v);
if (u != v) fa[u] = v;
if (Find(s) == Find(t)) {
ans = e[i].w;
break;
}
}
printf("Scenario #%d\n", cas++);
cout << ans << " tons" << endl << endl;
}
}