您的位置:首页 > 其它

codevs 1001 舒适的路线(并查集) 题解

2017-03-21 11:57 435 查看
链接:http://codevs.cn/problem/1001/

中文题,挺有意思的,寻找S到T的路径中最长路段比最短路段比值最小的路径的比值。一开始用DFS深搜,果然TLE了,不过其实可以注意到假设我们找到了一条通路,他的路段最大值为a,最小值为b,那么我们任意添加长度为a到b之间的路段,都不会影响最终的比值,不管这些路段有没有用,所以,我们只需要对边排序过后,枚举路段最小值,然后往右遍历边,不断维护并查集来维护连通性,当新增一边之后F(x)==F(y),则起点终点联通了,这就是以那条边为最小值的路径中的最大边。最后gcd约分一下答案,注意一下可能一条边就使起点终点联通了。

/*
作者:sega_hsj
题目:p1001 舒适的路线
*/
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#include<vector>
#include<string>
#include<cmath>
#include<set>
#include<queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
//const int mod = 1000000007;
const int maxm = 5005;
const int maxn = 505;
struct edge{
int from, to, len;
}e[maxm];

int n, m,s,t;
int ansa,ansb;
int f[maxn];
boo
4000
l vis[maxn];
int F(int x){
if (f[x] == x)return x;
return f[x] = F(f[x]);
}

bool cmp(edge a, edge b){
return a.len < b.len;
}

int gcd(int a, int b){
return b == 0 ? a : gcd(b, a%b);
}

int main() {
int x, y, z;
scanf("%d%d", &n, &m);
ansa = -1;
for (int i = 0; i < m; i++){
scanf("%d%d%d", &x, &y, &z);
e[i].from = x;
e[i].to = y;
e[i].len = z;
}
scanf("%d%d", &s, &t);
sort(e, e + m, cmp);
int cnta, cntb;
for (int i = 0; i < m; i++){
cnta=cntb = e[i].len;
for (int i = 1; i <= n; i++){ f[i] = i; }
f[e[i].to] = e[i].from;
if (F(s) == F(t)){
if (ansa == -1 || cntb*ansb < ansa*cnta){
ansa = cntb, ansb = cnta;
}
break;
}
for (int j = i + 1; j < m; j++){
cntb = e[j].len;
f[F(e[j].to)] = F(e[j].from);
if (F(s) == F(t)){
if (ansa == -1 || cntb*ansb < ansa*cnta){
ansa = cntb, ansb = cnta;
}
break;
}
}
}

if (ansa == -1){ printf("IMPOSSIBLE"); }
else{
int c = gcd(ansa, ansb);
ansa = ansa / c, ansb = ansb / c;
if (ansb == 1){ printf("%d", ansa); }
else{ printf("%d/%d", ansa, ansb); }
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: