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; }
相关文章推荐
- BZOJ1050 [HAOI2006]旅行
- BZOJ1050: [HAOI2006]旅行comf
- BZOJ 1050: [HAOI2006]旅行comf 贪心,并查集
- BZOJ 1050 [HAOI2006]旅行comf CODEVS 1001 舒适的路线 并查集
- bzoj 1050: [HAOI2006]旅行comf
- BZOJ 1050: [HAOI2006]旅行comf 并查集
- bzoj 1050: [HAOI2006] 旅行comf
- [bzoj1050][HAOI2006]旅行comf【MST】
- bzoj 1050 [HAOI2006]旅行comf (最小生成树)
- [BZOJ]1050 旅行comf(HAOI2006)
- bzoj1050 [HAOI2006]旅行comf
- 【bzoj1050】[HAOI2006]旅行comf 并查集
- [BZOJ1050][HAOI2006]旅行comf
- BZOJ 1050 HAOI 2006 旅行comf SPFA动态加点
- bzoj1050 [HAOI2006]旅行comf
- bzoj 1050: [HAOI2006]旅行comf(最小生成树+并查集)
- bzoj1050 [HAOI2006]旅行comf(并查集)
- bzoj1050: [HAOI2006]旅行comf
- [bzoj1050] [HAOI2006]旅行comf
- bzoj1050 [HAOI2006]旅行comf