1. 程式人生 > >codevs 1001 舒適的路線

codevs 1001 舒適的路線

name sam font 最大 輸出 車輛 資源 fault clas

題目描述 Description

Z小鎮是一個景色宜人的地方,吸引來自各地的觀光客來此旅遊觀光。
Z小鎮附近共有
N(1<N≤500)個景點(編號為1,2,3,…,N),這些景點被M(0<M≤5000)條道路連接著,所有道路都是雙向的,兩個景點之間可能有多條道路。也許是為了保護該地的旅遊資源,Z小鎮有個奇怪的規定,就是對於一條給定的公路Ri,任何在該公路上行駛的車輛速度必須為Vi。頻繁的改變速度使得遊客們很不舒服,因此大家從一個景點前往另一個景點的時候,都希望選擇行使過程中最大速度和最小速度的比盡可能小的路線,也就是所謂最舒適的路線。

輸入描述 Input Description

第一行包含兩個正整數,N和M。
接下來的M行每行包含三個正整數:x,y和v(1≤x,y≤N,0 最後一行包含兩個正整數s,t,表示想知道從景點s到景點t最大最小速度比最小的路徑。s和t不可能相同。

輸出描述 Output Description

如果景點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

數據範圍及提示 Data Size & Hint

N(1<N≤500)

M(0<M≤5000)

Vi在int範圍內

分析: 簡單的並查集,加上一點小貪心。類似最小生成樹。
首先將路線按照速度從小到大排序 枚舉每個最大速度 然後再找小於最大速度的路線 利用並查集 將邊聯通起來 構成個生成樹 看s,t是否可以聯通 找到直接比較更新max_ans與min_ans即可。
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
const int inf=9999999;
struct node{
    int s;
    int f;
    int w;
}a[5010];
int fx[501];
int gcd(int a,int b)
{
    return
b==0?a:gcd(b,a%b); } void init() { for(int i=1;i<=n;++i)fx[i]=i; } bool cmp(const node &a,const node &b) { return a.w<b.w; } int find(int n) { if(fx[n]==n)return n; else return fx[n]=find(fx[n]); } bool mer(int s,int f) { int a=find(s),b=find(f); if(a!=b) { fx[b]=a; return 1; } else return 0; } int main() { int max_ans=inf,min_ans=1; int s,t; cin>>n>>m; for(int i=1;i<=m;++i)cin>>a[i].s>>a[i].f>>a[i].w; cin>>s>>t; sort(a+1,a+m+1,cmp); for(int i=1;i<=m;++i) { init(); for(int j=i;j>=1;--j) { mer(a[j].s,a[j].f); if(find(s)==find(t)) { if((double)max_ans/min_ans>(double)a[i].w/a[j].w) { max_ans=a[i].w; min_ans=a[j].w; break; } } } } if(max_ans==inf&&min_ans==1) { cout<<"IMPOSSIBLE"; return 0; } //cout<<max_ans<<" "<<max_min; if(max_ans%min_ans==0) { cout<<max_ans/min_ans; } else { int t; t=gcd(max_ans,min_ans); max_ans/=t; min_ans/=t; cout<<max_ans<<"/"<<min_ans; } return 0; }

codevs 1001 舒適的路線