1. 程式人生 > >【UVA10816】Travel in Desert (最小瓶頸路+最短路)

【UVA10816】Travel in Desert (最小瓶頸路+最短路)

UVA10816 Travel in Desert

題目大意

沙漠中有一些道路,每個道路有一個溫度和距離,要求s,t兩點間的一條路徑,滿足溫度最大值最小,並且長度最短

輸入格式

輸入包含多組資料。

每組資料第一行為兩個整數\(n\)\(e\) 。表示綠洲數量和連線綠洲的道路數量。

每組資料第二行為兩個整數\(s\)\(t\) 。表示起點和終點的綠洲編號。

接下來\(e\) 行,每行包含兩個整數\(x,y\) 以及兩個實數\(d,r\) ,表明在綠洲\(x\)\(y\) 之間有一條雙向道路相連,長度為\(d\) ,溫度為\(r\)

輸出格式

對於輸入的每組資料,應輸出兩行,第一行表示你找到的路線,第二行包含兩個實數,為你找出的路線的總長度與途經的最高溫度。

輸入輸出樣例

輸入樣例#1:

6 9
1 6
1 2 37.1 10.2
2 3 40.5 20.7
3 4 42.8 19.0
3 1 38.3 15.8
4 5 39.7 11.1
6 3 36.0 22.5
5 6 43.9 10.2
2 6 44.2 15.2
4 6 34.2 17.4

輸出樣例#1:

1 3 6
38.3 38.3

題解

首先,說一下洛谷上翻譯有坑,輸入時是先輸入溫度\(r\),再輸入長度\(d\)

因為要讓最大值最小,所以很容易想到二分,但快\(NOIP\)了還是練了一下最小瓶頸路。

首先有兩道最小瓶頸路的題貨車運輸星際導航

我們發現這道題有兩個限制溫度和長度,不好處理,所以我們要去消除一層限制。

因為要首先保證最高溫度儘量小,所以先考慮溫度。

有些經驗的都應該能想到最小瓶頸路,跑出\(s\)\(t\)的最高溫度的最小值\(maxtem\)

然後把溫度不大於\(maxtem\)的邊加入圖中,跑最短路記錄路徑即可。

code:

#include<iostream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define N 10005
#define INF 0x3f3f3f3f
#define R register
using namespace std;
template<typename T>inline void read(T &a){
    char c=getchar();T x=0,f=1;
    while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    a=f*x;
}
int n,m,s,t,num,fa[N],tot,h[N];
double maxtem,dist[N];
bool vis[N];
vector<int> path;
struct MST{
    int u,v;
    double len,tem;
    friend bool operator < (const MST &a,const MST &b){
        return a.tem<b.tem;
    }
}tre[N];
struct node{
    int nex,to;
    double dis;
}edge[N<<1];
inline void add(R int u,R int v,R double w){
    edge[++tot].nex=h[u];
    edge[tot].to=v;
    edge[tot].dis=w;
    h[u]=tot;
}
inline void ins(R int u,R int v,R double w,R double t){
    tre[++num].u=u;
    tre[num].v=v;
    tre[num].len=w;
    tre[num].tem=t;
}
inline int find(R int x){
    if(x!=fa[x])fa[x]=find(fa[x]);
    return fa[x];
}
struct HeapNode{
    int u;
    double d;
    friend bool operator < (const HeapNode &a,const HeapNode &b){
        return a.d>b.d;
    }
};
priority_queue<HeapNode> q;
inline void dij(){
    for(R int i=1;i<=n;i++)dist[i]=INF,vis[i]=0,fa[i]=0;
    dist[s]=0;q.push((HeapNode){s,dist[s]});
    while(!q.empty()){
        R int x=q.top().u;q.pop();
        if(vis[x])continue;vis[x]=1;
        for(R int i=h[x];i;i=edge[i].nex){
            R int xx=edge[i].to;
            if(dist[xx]>dist[x]+edge[i].dis){
                dist[xx]=dist[x]+edge[i].dis;
                fa[xx]=x;
                q.push((HeapNode){xx,dist[xx]});
            }
        }
    }
    R int x=t;
    path.clear();
    while(x!=s){
        path.push_back(x);
        x=fa[x];
    }
    path.push_back(s);
    for(R int i=path.size()-1;i>=1;i--)
        printf("%d ",path[i]);
    printf("%d",path[0]);
    printf("\n");
}
int main(){
    while(scanf("%d%d",&n,&m)==2){
        num=tot=0;maxtem=0;
        memset(h,0,sizeof(h));
        memset(fa,0,sizeof(fa));
        read(s);read(t);
        R double w,te;
        for(R int i=1,u,v;i<=m;i++){
            read(u);read(v);scanf("%lf%lf",&te,&w);
            ins(u,v,w,te);
        }
        for(R int i=1;i<=n;i++)fa[i]=i;
        sort(tre+1,tre+1+m);
        for(R int i=1;i<=m;i++){
            R int x=find(tre[i].u),y=find(tre[i].v);
            if(x!=y){
                fa[x]=y;
                maxtem=max(maxtem,tre[i].tem);
                if(find(s)==find(t))break;
            }
        }
        for(R int i=1;i<=m;i++){
            if(tre[i].tem>maxtem)continue;
            add(tre[i].u,tre[i].v,tre[i].len);
            add(tre[i].v,tre[i].u,tre[i].len);
        }
        dij();
        printf("%.1f %.1f\n",dist[t],maxtem);
    }
    return 0;
}