【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 }
View Code

1050: [HAOI2006]旅行comf

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 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

Sample Output

【样例输出1】
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2

HINT

【数据范围】

1<  N < = 500

1 < = x, y < = N,0 < v < 30000,x ≠ y

0 < M < =5000

Source

[Submit][Status][Discuss]

 

posted @ 2015-04-16 21:27  Tunix  阅读(270)  评论(0编辑  收藏  举报