您的位置:首页 > 其它

BZOJ 1050 [HAOI2006]旅行comf Kruskal

2017-07-15 19:34 169 查看

Description

给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T,求
一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个
比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。

Input

第一行包含两个正整数,N和M。下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向公路
,车辆必须以速度v在该公路上行驶。最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速度比
最小的路径。s和t不可能相同。
1<N<=500,1<=x,y<=N,0<v<30000,0<M<=5000

Output

如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。
如果需要,输出一个既约分数。

Sample Input

【样例输入1】

4 2

1 2 1

3 4 2

1 4

【样例输入2】

3 3

1 2 10

1 2 5

2 3 8

1 3

【样例输入3】

3 2

1 2 2

2 3 4

1 3

Sample Output

【样例输出1】

IMPOSSIBLE

【样例输出2】

5/4

【样例输出3】

2

HINT

Source

传送门
利用贪心的思想。
首先我们把边按照边权升序排序。

然后我们看到假设我们枚举一条边x,
将它作为S~T的最小边,
那么接下来不停地加入比x边权更大的边,并且一条条加入,
直到S和T联通为止(也就是Kruskal)
我们可以看到中间的边权都是最大和最小之间的,是没有用的。
这样子O(M^2)的时间去枚举就可以得到解。

注意一下v是会到30000的……
一开始MAX设了个30000结果90分???
后来MAX改大就过了。

提一下,如果这题N,M都提升到100000呢,怎么做?
其实这题是可以用LCT优化的…
每次删除最小边,然后加入新的最小边,接着求解S~T的连通性。
因为删边最多成为不联通,所以最大值肯定是往后扩展的。
时间复杂度优化到了O(M*LogN)
(没有仔细算过的……)
当然这题写什么LCT啊……
其实闲的话也可以练练的。。

#include<bits/stdc++.h>
using namespace std;
int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int
N=505,
M=5005,
MAX=50000;
int n,m,fa
;
struct Edge{
int L,R,val;
}E[M];
bool cmp(Edge x,Edge y){
return x.val<y.val;
}
int gcd(int a,int b){
if (!b) return a;
else return gcd(b,a%b);
}
int getfa(int x){
if (fa[x]!=x) fa[x]=getfa(fa[x]);
return fa[x];
}
void unn(int x,int y){
int t1=getfa(x),
t2=getfa(y);
if (t1!=t2) fa[t2]=t1;
}
int main(){
n=read(),m=read();
for (int i=1;i<=m;i++)
E[i].L=read(),E[i].R=read(),E[i].val=read();
int S=read(),T=read();
sort(E+1,E+1+m,cmp);
int ansx=MAX,ansy=1,tx,ty;
for (int i=1;i<=m;i++){
for (int j=1;j<=n;j++) fa[j]=j;
ty=E[i].val; tx=MAX;
for (int j=i;j<=m;j++){
unn(E[j].L,E[j].R);
if (getfa(S)==getfa(T)){
tx=E[j].val;
break;
}
}
if ((double)tx/(double)ty<
(double)ansx/(double)ansy)
ansx=tx,ansy=ty;
}
if (ansx==MAX) puts("IMPOSSIBLE");
else{
int t=gcd(ansx,ansy);
ansx/=t,ansy/=t;
if (ansx%ansy)
printf("%d/%d\n",ansx,ansy);
else
printf("%d\n",ansx/ansy);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: