【UVA10816】Travel in Desert (最小瓶頸路+最短路)
阿新 • • 發佈:2018-11-06
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; }