题目链接 https://cn.vjudge.net/problem/UVA-10816
【题意】
给定一个n个点m条边的无向带权图(n<=100,m<=10000)以及起点和终点。边上有两种权值,路径长度和温度,要求在所走路径中的温度的最大值最小的前提下,走最短路径,输出路径以及最大温度和对应的长度.
【思路】
先用最小瓶颈路求出这个最大温度,然后将边权中所有温度不低于此温度的边加入新图中,在新图里跑最短路
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1050;
struct Edge {
int from,to;
double dist;
Edge(int f, int t, double d) :from(f), to(t), dist(d) {}
};
struct Edge2{
int from,to;
double r,d;
Edge2(int f,int t,double rr,double dd):from(f),to(t),r(rr),d(dd){}
bool operator<(const Edge2& e)const{
return r<e.r;
}
};
struct HeapNode {
int u;
double d;
HeapNode(double dd, int uu) :d(dd), u(uu) {}
bool operator < (const HeapNode& rhs) const {
return d > rhs.d;
}
};
struct Dijkstra {
int n, m, s, t; //点数和边数
vector<Edge> edges; //边列表
vector<int> g[maxn];//每个结点出发的边编号(从0开始)
bool done[maxn]; //是否永久标号
double d[maxn]; //s到各个点的距离
int p[maxn]; //最短路中的上一条边
void init(int n,int s,int t) {
this->n = n;
this->s = s;
this->t = t;
for (int i = 0; i < n; ++i) g[i].clear(); //清空邻接表
edges.clear(); //清空边表
}
void add(int from, int to, double dist) { //如果是无向图,每次加边调用两次
edges.push_back(Edge(from, to, dist));
m = edges.size();
g[from].push_back(m - 1);
}
void dijkstra(int s) { //s为源点
priority_queue<HeapNode> que;
for (int i = 0; i < n; ++i) d[i] = inf;
d[s] = 0;
memset(done, 0, sizeof(done));
que.push(HeapNode(0, s));
while (!que.empty()) {
HeapNode x = que.top();
que.pop();
int u = x.u;
if (done[u]) continue;
done[u] = true;
for (int i = 0; i < g[u].size(); ++i) {
Edge& e = edges[g[u][i]];
if (d[e.to] > d[u] + e.dist) {
d[e.to] = d[u] + e.dist;
p[e.to] = g[u][i];
que.push(HeapNode(d[e.to], e.to));
}
}
}
}
void print(int x) {//递归打印以x为终点的最短路径
if (x == s) {
printf("%d",1+x);
return;
}
Edge& e = edges[p[x]];
print(e.from);
printf(" %d",1+x);
}
};
int n, m, s, t;
int par[maxn];
Dijkstra dij;
vector<Edge2> edges;
int find(int x){ return x==par[x]?x:par[x]=find(par[x]); }
double kruscal(){
for(int i=0;i<n;++i) par[i]=i;
sort(edges.begin(),edges.end());
for(int i=0;i<m;++i){
Edge2& e=edges[i];
int x=find(e.from);
int y=find(e.to);
if(x!=y){
par[x]=y;
if(find(s)==find(t)) return e.r;
}
}
return 0;
}
int main(){
while(scanf("%d%d%d%d",&n,&m,&s,&t)==4){
--s;--t;
edges.clear();
for(int i=0;i<m;++i){
int u,v;
double r,d;
scanf("%d%d%lf%lf",&u,&v,&r,&d);
--u;--v;
edges.push_back(Edge2(u,v,r,d));
}
double ans=kruscal();
dij.init(n,s,t);
for(int i=0;i<m;++i){
Edge2& e=edges[i];
if(e.r<=ans){
dij.add(e.from,e.to,e.d);
dij.add(e.to,e.from,e.d);
}
}
dij.dijkstra(s);
dij.print(t);
puts("");
printf("%.1lf %.1lf\n",dij.d[t],ans);
}
return 0;
}