题意:给你一个n个点m条边的无向图 每条边有一个长度和一个温度 问你找出一条从起点到终点 最大温度最小的路 如果存在多条 则输出距离最短的那一条
思路:这道题目有两种方法 第一种就是二分温度跑最短路 我用的是第二种方法 即 先求出最小生成树 最低温度一定存在于最小生成树中 然后dfs找出起点到终点的最大温度 跑一边spfa 过滤掉温度大于该温度的边 记录前驱结点 最后输出即可 代码写的有点乱 - -
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define bug puts("bug")
const int maxn = 100 + 10;
const int maxe = 20000 + 10;
const double INF = 1e9;
struct Edge{
int v;
double t, d;
int next;
Edge(int v = 0, double t = 0, double d = 0, int next = 0) : v(v), t(t), d(d), next(next) {}
};
struct Edge2{
int u, v;
double t;
Edge2(int u = 0, int v= 0, double t = 0) : u(u), v(v), t(t) {}
bool operator < (const Edge2 &rhs) const{
return t < rhs.t;
}
};
int STACK[maxn], top;
int vis[maxn];
int pre[maxn];
int pa[maxn];
double dist[maxn];
double cost[maxn];//到起点的最大温度
int n, m, st, ed;
int Head[2][maxn], cntE[2];
Edge edge[2][maxe];
Edge2 e[maxe];
void init(){
memset(Head, -1, sizeof(Head));
cntE[1] = cntE[0] = 0;
}
void add(int u, int v, double t, double d, int i){
edge[i][cntE[i]] = Edge(v, t, d, Head[i][u]);
Head[i][u] = cntE[i]++;
edge[i][cntE[i]] = Edge(u, t, d, Head[i][v]);
Head[i][v] = cntE[i]++;
}
int find_set(int x){
return pa[x] == x ? x : pa[x] = find_set(pa[x]);
}
void Kruscal(){
for(int i = 0;i < n; i++) pa[i] = i;
sort(e, e + m);
int cnt = 0;
for(int i = 0; i < m;i++){
int x= find_set(e[i].u);
int y = find_set(e[i].v);
if(x != y){
pa[x] = y;
add(e[i].u, e[i].v, e[i].t, 0, 1);
if(++cnt == n-1) return;
}
}
}
void spfa(int s, double max_t){
memset(vis, 0, sizeof(vis));
for(int i = 0; i < n; i++) dist[i] = INF;
dist[s] = 0;
vis[s] = 1;
top = 0;
STACK[top++] = s;
while(top){
int u = STACK[--top];
vis[u] = 0;
for(int i = Head[0][u]; ~i; i = edge[0][i].next){
int v = edge[0][i].v;
if(edge[0][i].t > max_t) continue;
if(dist[v] > dist[u] + edge[0][i].d){
dist[v] = dist[u] + edge[0][i].d;
pre[v] = u;
if(!vis[v]){
vis[v] = 1;
STACK[top++] = v;
}
}
}
}
}
void dfs(int u, double cur_max){
vis[u] = 1;
for(int i = Head[1][u]; ~i; i = edge[1][i].next){
int v = edge[1][i].v;
if(vis[v]) continue;
cost[v] = max(cur_max, edge[1][i].t);
dfs(v, cost[v]);
}
}
void print(int x){
if(pre[x] == -1){
printf("%d", x + 1);
return;
}
print(pre[x]);
printf(" %d", x + 1);
}
void solve(){
scanf("%d%d", &st, &ed);
--st; --ed;
init();
for(int i = 0; i < m; i++){
int u, v;
double t, d;
scanf("%d%d%lf%lf", &u, &v, &t, &d);
--u; --v;
add(u, v, t, d, 0);
e[i] = Edge2(u, v, t);
}
Kruscal();
memset(cost, 0, sizeof(cost));
memset(vis, 0, sizeof(vis));
memset(pre, -1, sizeof(pre));
dfs(st, 0);
spfa(st, cost[ed]);
print(ed);
printf("\n");
printf("%.1lf %.1lf\n", dist[ed], cost[ed]);
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF) solve();
return 0;
}
/*
6 9
6 1
1 2 37.1 10.2
2 3 40.5 20.7
3 4 38.3 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 1.00
*/