BZOJ [HAOI2006]旅行comf

题解:枚举最大边,然后对<=最大边的边做最大生成树,使最小边最大

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=100009;
const int oo=1000000000;

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

double ans=oo;
int ansa,ansb;

int n,m;
int s,t;

int father[maxn];
int Getf(int x){
	if(father[x]==x)return x;
	return father[x]=Getf(father[x]);
}
void Unionn(int x,int y){
	int fx=Getf(x);
	int fy=Getf(y);
	if(fx!=fy)father[fx]=fy;
}

struct Edge{
	int u,v,d;
}edges[maxn];
bool cmp(const Edge &rhs1,const Edge &rhs2){
	return rhs1.d<rhs2.d;
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;++i)scanf("%d%d%d",&edges[i].u,&edges[i].v,&edges[i].d);
	sort(edges+1,edges+1+m,cmp);
	scanf("%d%d",&s,&t);
	for(int i=1;i<=m;++i){
		for(int j=1;j<=n;++j)father[j]=j;
		Unionn(edges[i].u,edges[i].v);
		if(Getf(s)==Getf(t)){
			printf("1\n");
			return 0;
		}
		for(int j=i-1;j;--j){
			int u=edges[j].u;
			int v=edges[j].v;
			if(Getf(u)!=Getf(v)){
				Unionn(u,v);
			}
			if(Getf(s)==Getf(t)){
				if(1.0*edges[i].d/edges[j].d<ans){
					ansa=edges[i].d;
					ansb=edges[j].d;
					ans=1.0*edges[i].d/edges[j].d;
				}
				break;
			}
		}
	}

	if(ans>oo-1){
		printf("IMPOSSIBLE\n");
	}else{
		int d=Gcd(ansa,ansb);
		ansa/=d;
		ansb/=d;
		if(ansb==1)printf("%d\n",ansa);
		else printf("%d/%d\n",ansa,ansb);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/zzyer/p/8457061.html

时间: 2024-08-28 09:17:27

BZOJ [HAOI2006]旅行comf的相关文章

BZOJ 1050: [HAOI2006]旅行comf(枚举+并查集)

[HAOI2006]旅行comf Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小.如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需要,表示成一个既约分数. 备注: 两个顶点之间可能有多条路径. Input 第一行包含两个正整数,N和M.下来的M行每行包含三个正整数:x,y和v.表示景点x到景点y之间有一条

bzoj 1050: [HAOI2006]旅行comf(最小生成树+并查集)

1050: [HAOI2006]旅行comf Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2405  Solved: 1282 [Submit][Status][Discuss] Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T ,求一条路径,使得路径上最大边和最小边的比值最小.如果S和T之间没有路径,输出"IMPOSS

1050: [HAOI2006]旅行comf

1050: [HAOI2006]旅行comf Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1495  Solved: 737[Submit][Status] Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小.如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需

BZOJ 1050 旅行comf(枚举最小边-并查集)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1050 题意:给出一个带权图.求一条s到t的路径使得这条路径上最大最小边的比值最小? 思路:将边排序.枚举最小边,然后将边一个一个插到并查集里,s和t联通时计算更新答案. struct node { int u,v,w; void get() { RD(u,v,w); } }; int cmp(node a,node b) { return a.w<b.w; } int n,m,s,t;

[HAOI2006]旅行comf

1050: [HAOI2006]旅行comf Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 3450  Solved: 1919 [Submit][Status][Discuss] Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求 一条路径,使得路径上最大边和最小边的比值最小.如果S和T之间没有路径,输出"IMPOSS

[BZOJ]1050 旅行comf(HAOI2006)

图论一直是小C的弱项,相比其它题型,图论的花样通常会更多一点,套路也更难捉摸. Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小.如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个比值,如果需要,表示成一个既约分数. 备注: 两个顶点之间可能有多条路径. Input 第一行包含两个正整数,N和M.下来的M行每行包含三个正

bzoj 1050: [HAOI2006]旅行comf&amp;&amp;【codevs1001】

Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求 一条路径,使得路径上最大边和最小边的比值最小.如果S和T之间没有路径,输出"IMPOSSIBLE",否则输出这个 比值,如果需要,表示成一个既约分数. 备注: 两个顶点之间可能有多条路径. Input 第一行包含两个正整数,N和M.下来的M行每行包含三个正整数:x,y和v.表示景点x到景点y之间有一条双向公路

BZOJ 1050 HAOI2006 旅行comf 动点SPFA

题目大意:给定一个无向图,每条边上有权值,求起点到终点的路径中最长边和最短边的最小比值 随手点开一道居然是动点SPFA的裸题-- 魔法森林都切了这个问题就不大了 我们把边权排序,从大到小加进这个图中,每加进一条边就把边的两个端点加进队列,直接跑SPFA,维护起点到每个点路径上的最长边的最小值,然后用当前边权作为分母更新ans 这样可以保证每次跑出来的都是当前边为最短边时起点到终点的最长边的最小值,同时由于我们保留了上一次的信息而不至于超时 好强大的算法--可惜搞不出来时间复杂度0.0 #incl

bzoj 1050 [HAOI2006]旅行comf

题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1050 思路: 先将每条边的权值排个序优先小的,然后从小到大枚举每一条边,将其存到并查集里,如果得到的比值比之前的小,那么判断下s与t能否连通,如果连通就替换就好了 实现代码: #include<bits/stdc++.h> using namespace std; const int M = 1e6+10; int f[M],vis[M],a[M]; int n,m; int Fi