bzoj 1050 旅行comf

题目大意:

一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)

两个顶点S和T,求一条路径,使得路径上最大边和最小边的比值最小

如果S和T之间没有路径,输出”IMPOSSIBLE” 否则输出这个比值(最简)

思路:

我们可以枚举所有边的下限

先按边权排序

然后从这条边开始向上枚举直到联通找到最大边

再清空所有关系,从最顶端的边向下枚举找到最小边

这样这个最大边/最小边的值为一个答案,在所有这些值中找一个最小值

然后把下限变为这个最小值+1

重复操作

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #include<cstring>
 7 #include<queue>
 8 #include<map>
 9 #include<vector>
10 #define ll long long
11 #define inf 2147483611
12 #define MAXN 510
13 using namespace std;
14 inline int read()
15 {
16     int x=0,f=1;char ch=getchar();
17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
19     return x*f;
20 }
21 int f[MAXN],mx,mn,n,m,s,t,ansmx,ansmn;
22 struct data 
23 {
24     int u,v,val;
25     bool operator < (const data &a) const
26     {
27         return val<a.val;
28     }
29 }e[MAXN*10];
30 int find(int x) {return x==f[x]?x:f[x]=find(f[x]);}
31 int gcd(int a,int b) {return !b?a:gcd(b,a%b);}
32 void mem() {for(int i=1;i<=n;i++) f[i]=i;}
33 int main()
34 {
35     n=read(),m=read();
36     for(int i=1;i<=m;i++)
37         e[i].u=read(),e[i].v=read(),e[i].val=read();
38     sort(e+1,e+m+1);
39     s=read(),t=read();
40     int a,b,st=1;ansmx=inf,ansmn=1;
41     int i;
42     while(st<=m)
43     {
44         mem();mn=inf,mx=-1;
45         //cout<<i<<endl;
46         for(i=st;i<=m;i++)
47         {
48         //cout<<i<<" "<<e[i].val<<endl;
49             a=find(e[i].u),b=find(e[i].v);
50             if(a!=b) f[a]=b;
51             if(find(s)==find(t)) {mx=e[i].val;break;}
52         }
53         //cout<<mx<<" "<<mn<<" "<<i<<endl;
54         if(mx==-1&&ansmx==inf) {printf("IMPOSSIBLE");return 0;}
55         if(mx==-1) break;
56         mem();
57         for(;i>=1;i--)
58         {
59             a=find(e[i].u),b=find(e[i].v);
60             if(a!=b) f[a]=b;
61             if(find(s)==find(t)) {mn=e[i].val;break;}
62         }
63         //cout<<mx<<" "<<mn<<" "<<i<<endl;
64         st=i+1;
65         if(mn==inf&&ansmx==inf) {printf("IMPOSSIBLE");return 0;}
66         if(mn==inf) break;
67         int g=gcd(mx,mn);mx/=g,mn/=g;
68         if((ll)ansmx*mn>(ll)ansmn*mx) ansmx=mx,ansmn=mn;
69         //cout<<ansmx<<"  "<<ansmn<<endl;
70         //system("pause");
71     }
72     if(ansmn!=1) printf("%d/%d",ansmx,ansmn);
73     else printf("%d",ansmx);
74 }
View Code

 

转载于:https://www.cnblogs.com/yyc-jack-0920/p/7886124.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值