题意:给出n个点,m条边,t 后跟m条边。
x, y, d, t x y 表示边的顶点,d 表示这条边可以运输的最大容量,t表示用的时间。
问从1 运到n 的最大容量,1 到n的最大容量为1到n这条路径上容量最小的那个边的容量。但这条边上所用的所有时间和不能大于给出的总时间 t 。
思路:当有两个边量同时变化时,由于时间问题我们无法枚举各变量,此时好的做法是先二分一个变量的值,去枚举另外一个变量,就是本题要用的 二分 + spfa算法;
开始我用的是二分+Dijstra算法,超时了,还是spfa快啊
#include <iostream>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;
const int inf = 99999999;
const int M = 10006;
struct node {
int to;
int time;
int len;
};
node cur;
int ans;
int dist[M];
int n, m, t;
int maxn, minn;
vector<node>road[M];
void init(){
maxn = 0;
minn = inf;
for(int i = 0; i <= n; i++)
road[i].clear();
}
void input() {
int x, y, d, time;
for(int i = 0; i < m; i++){
scanf("%d%d%d%d", &x, &y, &d, &time);
cur.to = y;
cur.len = d;
cur.time = time;
road[x].push_back(cur); //建立双向边;
cur.to = x;
road[y].push_back(cur);
maxn = max(maxn, d);
minn = min(minn, d);
}
}
bool spfa(int mid){
int cnt;
int dist[M], vist[M];
queue<int>que;
for(int i = 0; i <= n; i++){
dist[i] = inf;
vist[i] = 0;
}
vist[1] = 1;
dist[1] = 0;
que.push(1);
while(!que.empty()){
cnt = que.front();
que.pop();
vist[cnt] = 0;
for(int i = 0; i < (int)road[cnt].size(); i++){
cur = road[cnt][i];
if(dist[cur.to] > dist[cnt] + cur.time && cur.len >= mid && dist[cnt] + cur.time <= t){
dist[cur.to] = dist[cnt] + cur.time;
if(!vist[cur.to]){
vist[cur.to] = 1;
que.push(cur.to);
}
}
}
}
if(dist[n] != inf)
return true;
else
return false;
}
void work(){
// printf("%d %d\n", maxn, minn);
while(minn <= maxn){ //二分容量值;
int mid = (maxn + minn)/2;
//printf("%d\n", mid);
if(spfa(mid)){
ans = mid;
minn = mid + 1;
}else {
maxn = mid -1;
}
}
printf("%d\n", ans);
}
int main()
{
int Case;
scanf("%d", &Case);
while(Case--){
scanf("%d%d%d", &n, &m, &t);
init();
input();
work();
}
return 0;
}