【Luogu P2502】[HAOI2006]旅行

题目大意:

给定一个有 \(n\) 个点的无向图,求出从 \(s\)\(t\) 的最短路上的最大权值与最小权值的比。

正文:

并查集查询 \(s\)\(t\) 是否连通,可以通过给邻接表按权值从大到小排序,枚举每次连通的最大最小权值比即可。

代码:

int find_(int x) {if(x == fa[x])return x;return fa[x] = find_(fa[x]);}

void Add(int u, int v, int w)
{
	e[++tot] = (node){u, v, head[u], w}, head[u] = tot;
}

bool cmp(node a, node b)
{
	return a.w > b.w;
}

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

int main()
{
	scanf ("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) fa[i] = i;
	for (int i = 1; i <= m; i++)
	{
		int u, v, w;
		scanf("%d%d%d", &u, &v, &w);
		Add(u, v, w);
		fa[find_(u)] = find_(v);
	}
	scanf ("%d%d", &s, &t);
	if(find_(s) != find_(t))
	{
		puts("IMPOSSIBLE");
		return 0;
	}
	sort (e + 1, e + 1 + tot, cmp); 
	for (int i = 1; i <= m; i++)
	{
		for (int j = 1; j <= n; j++) fa[j] = j;
		for (int j = i; j <= m; j++)
		{
			int u = e[j].from, v = e[j].to;
			fa[find_(u)] = find_(v);
			if(find_(s) == find_(t))
			{
				double opt = e[i].w * 1.0 / e[j].w * 1.0;
				if(opt < ans) 
					maxsp = e[i].w, minsp = e[j].w, ans = opt;
				break;
			}
		}
	}
	if(maxsp % minsp) printf("%d/%d", maxsp / gcd(maxsp, minsp), minsp / gcd(maxsp, minsp));
	else printf("%d", maxsp / minsp);
	return 0;
}


posted @ 2020-07-21 09:50  Jayun  阅读(77)  评论(0编辑  收藏  举报