题目大意:
给你一幅图,图中的边带权,问你怎么找到图中两点u,v的一条路径,使得这条路径中权值最大的边是在所有uv路径中权值最大的边权值最小。有点绕,简单来说就是符合以下的一条公式约束
其中uv代表点u v之间的所有路径,i表示路径中的一条边。
解题思路:
首先我们可以用kruskal得到MST,然后u 和 v之间存在的路径即为最优路径,然后我们遍历一遍路径就可以了,输出路径中的最大权重即可,这条路径我们可以通过在MST中DFS然后用存父亲的方法来获得。若MST中不存在u和v,那么我们可以输出no path.
个人总结:
DFS写错了,真是要面壁思过...... 要记住节点遍历判重应该在for遍历子节点里面判重。一开始存父亲那里就是因为这里错了。
AC代码:
#include <bits/stdc++.h>
#define MAXN 200
#define UNVISITED 0
#define VISITED 1
using namespace std;
typedef vector<int > vi;
class UnionFind {
private:
vi p, rank, setSize;
int numSets;
public:
UnionFind(int N) {
p.assign(N, 0); rank.assign(N, 1); setSize.assign(N, 1);
numSets = N; for (int i = 0; i<N; i++)p[i] = i;
}
int find_set(int i) { return p[i] == i ? i : p[i] = find_set(p[i]); } //find the representative element(root of the tree)
bool issameset(int i, int j) {
//1 for same set
return find_set(i) == find_set(j);
}
void Unionset(int i, int j) {
if (!issameset(i, j)) {
int x = find_set(i); int y = find_set(j);
numSets--;
if (rank[x] < rank[y]) {
p[x] = y;
setSize[y] += setSize[x];
}
else {
p[y] = x;
setSize[x] += setSize[y];
if (rank[x] == rank[y])rank[x] ++;
}
}
}
int numDisjointsets() {
return numSets;
}
int sizeOfSet(int i) {
return setSize[find_set(i)];
}
};
vector<vector<pair<int, double> > > gra(MAXN);
int dfs_parent[MAXN];
int suc_flag;
int qu, qv;
int dfs_flag[MAXN];
void DFS(int u) {
// cerr<<u<<endl;
if (u == qv) { suc_flag = 1; return; }
dfs_flag[u] = VISITED;
for (int i = 0; i<(int)gra[u].size(); i++) {
int nx = gra[u][i].first;
if (dfs_flag[nx] == VISITED)continue;
dfs_parent[nx] = u;
DFS(nx);
}
}
int main() {
int c, s, q;
int ca = 0;
while (cin >> c >> s >> q && (c || s || q)) {
ca++;
vector<pair<double, pair<int, int>> > edges;
for (int i = 0; i<s; i++) {
int u, v;
double wei;
cin >> u >> v;
cin >> wei;
u -= 1;
v -= 1;
edges.push_back(make_pair(wei, make_pair(u, v)));
}
UnionFind djset(c);
sort(edges.begin(), edges.end(), less<pair< double, pair<int, int>>>());
for (int i = 0; i<MAXN; i++) {
gra[i].erase(gra[i].begin(), gra[i].end());
}
int exi[MAXN];
double Weight[MAXN][MAXN];
memset(exi, 0, sizeof(exi));
for (int i = 0; i<(int)edges.size(); i++) {
int u = edges[i].second.first;
int v = edges[i].second.second;
double wei = edges[i].first;
if (!djset.issameset(u, v)) {
djset.Unionset(u, v);
gra[u].emplace_back(v, wei);
gra[v].emplace_back(u, wei);
exi[u] = 1;
exi[v] = 1;
Weight[u][v] = wei;
Weight[v][u] = wei;
}
}
if (ca > 1)cout << endl;
cout << "Case #" << ca << endl;
for (int i = 0; i<q; i++) {
cin >> qu >> qv;
qu -= 1;
qv -= 1;
suc_flag = 0;
memset(dfs_flag, UNVISITED, sizeof(dfs_flag));
if (exi[qu])
DFS(qu);
if (!suc_flag)cout << "no path" << endl;
else {
double min_wei = -1;
for (int u = qv; u != qu; u = dfs_parent[u]) {//dfs parent
//cerr << u << endl;
double wei = Weight[u][dfs_parent[u]];
min_wei = max(min_wei, wei);
}
cout << min_wei << endl;
}
}
}
return 0;
}