【BZOJ】【1050】【HAOI2006】旅行comf
枚举/暴力/Kruskal
orz……我sb了……其实是sb题<_<
有一道题问的是最小极差生成树……(不记得是什么名字了,就是求最大边权与最小边权差最小的生成树)做法是枚举最小边,然后kruskal找最大边
这题同理,因为$m\leq 5000$,所以$m^2$的算法即可……
1 /************************************************************** 2 Problem: 1050 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:312 ms 7 Memory:1336 kb 8 ****************************************************************/ 9 10 //BZOJ 1050 11 #include<vector> 12 #include<cstdio> 13 #include<cstring> 14 #include<cstdlib> 15 #include<iostream> 16 #include<algorithm> 17 #define rep(i,n) for(int i=0;i<n;++i) 18 #define F(i,j,n) for(int i=j;i<=n;++i) 19 #define D(i,j,n) for(int i=j;i>=n;--i) 20 #define pb push_back 21 using namespace std; 22 inline int getint(){ 23 int v=0,sign=1; char ch=getchar(); 24 while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();} 25 while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();} 26 return v*sign; 27 } 28 const int N=510,M=5010,INF=~0u>>2; 29 typedef long long LL; 30 /******************tamplate*********************/ 31 int n,m,s,t,fa[N]; 32 struct edge{int x,y,v;}e[M]; 33 inline bool cmp(edge a,edge b){return a.v<b.v;} 34 inline int Find(int x){return fa[x]==x?x:Find(fa[x]);} 35 inline int gcd(int a,int b){return b?gcd(b,a%b):a;} 36 int main(){ 37 #ifndef ONLINE_JUDGE 38 freopen("1050.in","r",stdin); 39 freopen("1050.out","w",stdout); 40 #endif 41 n=getint(); m=getint(); 42 F(i,1,m){ 43 e[i].x=getint(); e[i].y=getint(); e[i].v=getint(); 44 } 45 s=getint(); t=getint(); 46 sort(e+1,e+m+1,cmp); 47 int j,min=-1,max=-1; 48 F(i,1,m){ 49 if (e[i].v==e[i-1].v)continue; 50 for(j=1;j<=n;j++) fa[j]=j; 51 for(j=i;j<=m;j++){ 52 int f1=Find(e[j].x),f2=Find(e[j].y); 53 if (f1!=f2) fa[f1]=f2; 54 if (Find(s)==Find(t)) break; 55 } 56 if (j<=m && (min==-1||double(max)/min>double(e[j].v)/e[i].v)){ 57 min=e[i].v; 58 max=e[j].v; 59 } 60 } 61 if (min==-1) puts("IMPOSSIBLE"); 62 else{ 63 if (max%min==0) printf("%d\n",max/min); 64 else printf("%d/%d\n",max/gcd(max,min),min/gcd(max,min)); 65 } 66 return 0; 67 }
1050: [HAOI2006]旅行comf
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1693 Solved: 849
[Submit][Status][Discuss]
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不可能相同。
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
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
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2
HINT
【数据范围】
1< N < = 500
1 < = x, y < = N,0 < v < 30000,x ≠ y
0 < M < =5000
Source