题意:
给你一张无向图,然后有若干组询问,让你输出a->b的最小瓶颈路。
解析:
应该都想过用prime的次小生成树做。。但二维数组开不了那么大。。所以只能用kruskal了。。。。
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <queue> #include <algorithm> #include <cmath> #define rap(i, a, n) for(int i=a; i<=n; i++) #define MOD 2018 #define LL long long #define ULL unsigned long long #define Pair pair<int, int> #define mem(a, b) memset(a, b, sizeof(a)) #define _ ios_base::sync_with_stdio(0),cin.tie(0) //freopen("1.txt", "r", stdin); using namespace std; const int maxn = 50010, INF = 0x7fffffff, maxm = 1e5+10; int n, m; int f[maxn], ra[maxn], vis[maxn], edge[maxn]; struct node { int u, v, w; }Node[maxm]; bool cmp(node a, node b) { return a.w < b.w; } int find(int x) { return f[x] == x ? x : find(f[x]); } int query(int x, int y) { int ans1 = 0, ans2 = -1; int cur = x; while(1) //从x回溯到祖先 { vis[cur] = ans1; //标记 从x到当前cur的最大权值的路段 if(cur == f[cur]) break; ans1 = max(ans1, edge[cur]); cur = f[cur]; } cur = y; while(1) //从y回溯到祖先 { if(vis[cur] >= 0) //直到遇到y和x的最近公共祖先 { ans2 = max(ans2, vis[cur]); break; } ans2 = max(ans2, edge[cur]); cur = f[cur]; } cur = x; while(1) //还原vis。。其实用一个memset就好了。。但时间复杂度竟然比用这个大10倍。。emm。。。 { vis[cur] = -1; if(cur == f[cur]) break; cur = f[cur]; } return ans2; } void init() { rap(i, 1, n) { f[i] = i; ra[i] =1; } mem(vis, -1); } int main() { bool flag = true; while(~scanf("%d%d", &n, &m)) { init(); rap(i, 1, m) { scanf("%d%d%d", &Node[i].u, &Node[i].v, &Node[i].w); } sort(Node+1, Node+m+1, cmp); rap(i, 1, m) //按秩合并 { int l = find(Node[i].u); int r = find(Node[i].v); if(l == r) continue; if(ra[l] <= ra[r]) f[l] = r, ra[r] = max(ra[r], ra[l] + 1), edge[l] = Node[i].w; //儿子标记权值 else f[r] = l, ra[l] = max(ra[l], ra[r] + 1), edge[r] = Node[i].w; } if(flag) flag = false; else printf("\n"); int q; scanf("%d", &q); rap(i, 1, q) { int u, v; scanf("%d%d", &u, &v); printf("%d\n", query(u, v)); } } return 0; }