HDU1839
题意:每条边都有容量和时间把矿物从1运到n,并且不超过规定的时间T。且路线的容量要最大。这一条路线的容量为容量最小边的容量
题解:把每一条边的容量进行排序,然后按二分容量,枚举容量最小的边。走容量≥limit的边。一开始我用邻接表,然后内部排序,但我没有考虑到邻接表利用边的编号,所以这样一排序就乱了。所以只用记录容量,然后对容量进行排序,再二分。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
int const N = 10000 + 10;
int const inf = 0x3f3f3f3f;
int const M = 50000 + 10;
int first[N],n,m,t,tot;
int dis[N],a[M];
struct Edge
{
int next,from,to,cap,time;
}edge[M<<1];
void add(int from,int to,int cap,int time){
edge[++tot] = (Edge){first[from],from,to,cap,time};
first[from] = tot;
}
bool vis[N];
priority_queue<pii,vector<pii>,greater<pii> >q;
bool Dijkstra(int limit){
for(int i=0;i<=n;i++) dis[i] = inf,vis[i] = false;
dis[1] = 0;
q.push(make_pair(0,1));
while(!q.empty()){
pii p = q.top(); q.pop();
int u = p.second;
if(vis[u]) continue;
vis[u] = true;
for(int i=first[u];i;i=edge[i].next){
int to = edge[i].to;
if(!vis[to] && edge[i].cap >= limit && dis[to] > dis[u] + edge[i].time){
dis[to] = dis[u] + edge[i].time;
q.push(make_pair(dis[to],to));
}
}
}
return dis[n] <= t;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&t);
tot = 0;
memset(first,0,sizeof(first));
for(int i=0;i<m;i++){
int from,to,cap,time;
scanf("%d%d%d%d",&from,&to,&cap,&time);
a[i] = cap;
add(from,to,cap,time); add(to,from,cap,time);
}
sort(a,a+m);
int l = 0,r = m-1,ans;
while(l <= r){
int mid = (l + r) >> 1;
if(Dijkstra(a[mid])){
l = mid + 1;
ans = a[mid];
}else{
r = mid - 1;
}
}
printf("%d\n",ans);
}
return 0;
}