BZOJ 1050 旅行comf 并查集+枚举下界
题目链接:
https://www.lydsy.com/JudgeOnline/problem.php?id=1050
题目大意:
给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。
思路:
枚举最小的边,逐步按照权值从小到大将边加入并查集中,直到s-t连通为止。
每次保留最小的ans(分数)即可。
1 #include<bits/stdc++.h> 2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf 3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时 4 #define Min(a, b) ((a) < (b) ? (a) : (b)) 5 #define Mem(a) memset(a, 0, sizeof(a)) 6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1)) 7 #define MID(l, r) ((l) + ((r) - (l)) / 2) 8 #define lson ((o)<<1) 9 #define rson ((o)<<1|1) 10 #define Accepted 0 11 #pragma comment(linker, "/STACK:102400000,102400000")//栈外挂 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 17 while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 21 typedef long long ll; 22 const int maxn = 10000 + 10; 23 const int MOD = 1000000007;//const引用更快,宏定义也更快 24 const int INF = 1e9 + 7; 25 const double eps = 1e-6; 26 27 struct edge 28 { 29 int u, v, w; 30 edge(){} 31 edge(int u, int v, int w):u(u), v(v), w(w){} 32 bool operator < (const edge& a)const 33 { 34 return w < a.w; 35 } 36 }; 37 vector<edge>e; 38 int p[maxn]; 39 vector<int>G[maxn]; 40 void addedge(int u, int v, int w) 41 { 42 e.push_back(edge(u, v, w)); 43 G[u].push_back(e.size() - 1); 44 e.push_back(edge(v, u, w)); 45 G[v].push_back(e.size() - 1); 46 } 47 int Find(int x) 48 { 49 return x == p[x] ? x : p[x] = Find(p[x]); 50 } 51 struct node 52 { 53 int a, b; 54 node(){} 55 node(int A, int B) 56 { 57 int g = __gcd(A, B); 58 a = A / g, b = B / g; 59 } 60 bool operator < (const node& tmp)const 61 { 62 return a * tmp.b < b * tmp.a; 63 } 64 }; 65 66 int main() 67 { 68 int n, m, u, v, w, s, t; 69 scanf("%d%d", &n, &m); 70 while(m--) 71 { 72 scanf("%d%d%d", &u, &v, &w); 73 addedge(u, v, w); 74 } 75 scanf("%d%d", &s, &t); 76 sort(e.begin(), e.end()); 77 m = e.size(); 78 node ans(1, 0);//最大 79 for(int start = 0; start < m; start++)//枚举下限 80 { 81 for(int i = 1; i <= n; i++)p[i] = i;//初始化并查集 82 int cnt = -INF; 83 for(int i = start; i < m; i++) 84 { 85 int u = e[i].u, v = e[i].v, w = e[i].w; 86 u = Find(u); 87 v = Find(v); 88 p[u] = v; 89 if(Find(s) == Find(t)) 90 { 91 cnt = w; 92 break; 93 } 94 } 95 if(cnt == -INF) 96 { 97 break; 98 } 99 ans = min(ans, node(cnt, e[start].w)); 100 } 101 if(ans.a == 1 && ans.b == 0)puts("IMPOSSIBLE\n"); 102 else if(ans.b != 1)printf("%d/%d\n", ans.a, ans.b); 103 else printf("%d\n", ans.a); 104 return Accepted; 105 }
越努力,越幸运