bzoj 1050: [HAOI2006]旅行comf 并查集
1050: [HAOI2006]旅行comf
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2254 Solved: 1202
[Submit][Status][Discuss]
Description
给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。
Input
第一行包含两个正整数,N和M。 下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路,车辆必须以速度v在该公路上行驶。 最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比最小的路径。s和t不可能相同。
Output
如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。
Sample Input
【样例输入1】
4 2
1 2 1
3 4 2
1 4
【样例输入2】
3 3
1 2 10
1 2 5
2 3 8
1 3
【样例输入3】
3 2
1 2 2
2 3 4
1 3
4 2
1 2 1
3 4 2
1 4
【样例输入2】
3 3
1 2 10
1 2 5
2 3 8
1 3
【样例输入3】
3 2
1 2 2
2 3 4
1 3
Sample Output
【样例输出1】
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2
按边权大小排序, 然后开始枚举, i从1开始, 不停加边直到s和t联通, 设此时为r, 将并查集初始化, 从r开始反向枚举, 直到st联通, 这时为l, 那么[l, r]就是一个可能的解。 然后i变为l+1, 继续枚举。
我也不知道为什么这样对...
#include <iostream> #include <vector> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <map> #include <set> #include <string> #include <queue> #include <stack> #include <bitset> using namespace std; #define pb(x) push_back(x) #define ll long long #define mk(x, y) make_pair(x, y) #define lson l, m, rt<<1 #define mem(a) memset(a, 0, sizeof(a)) #define rson m+1, r, rt<<1|1 #define mem1(a) memset(a, -1, sizeof(a)) #define mem2(a) memset(a, 0x3f, sizeof(a)) #define rep(i, n, a) for(int i = a; i<n; i++) #define fi first #define se second typedef pair<int, int> pll; const double PI = acos(-1.0); const double eps = 1e-8; const int mod = 1e9+7; const int inf = 1061109567; const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; struct node { int u, v, w; bool operator < (node a)const { return w<a.w; } }a[5005]; int f[505], n; void init() { for(int i = 1; i<=n; i++) f[i] = i; } int findd(int u) { return f[u] == u?u:f[u] = findd(f[u]); } int gcd(int a, int b) { return b?gcd(b, a%b):a; } int main() { int m, s, t, maxx, minn; cin>>n>>m; for(int i = 0; i<m; i++) { scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].w); } cin>>s>>t; sort(a, a+m); double ans = inf; for(int i = 0, j; i<m; ) { init(); int flag = 0; for(j = i; j<m; j++) { int u = findd(a[j].u); int v = findd(a[j].v); if(u != v) { f[u] = v; } if(findd(s) == findd(t)) { flag = 1; break; } } if(flag) { init(); int k; for(k = j; ; k--) { int u = findd(a[k].u); int v = findd(a[k].v); if(u!=v) f[u] = v; if(findd(s) == findd(t)) break; } if(ans>1.0*a[j].w/a[k].w) { maxx = a[j].w; minn = a[k].w; ans = 1.0*a[j].w/a[k].w; } i = k+1; } else { break; } } if(ans == inf) { puts("IMPOSSIBLE"); } else { int x = gcd(maxx, minn); if(minn/x==1) { printf("%d\n", maxx/x); } else { printf("%d/%d\n", maxx/x, minn/x); } } return 0; }