http://acm.hdu.edu.cn/showproblem.php?pid=1839
解题思路:二分+最短路
直接对答案进行二分枚举,然后用spfa求最短路,如果边的权值小于当前枚举的答案,那么这样的边是不能走的。
源代码:
//二分+最短路
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=10005;
const int maxm=100005;
const int INF= 2000000005;
int vis[maxm],first[maxn];
int to[maxm],next[maxm],cc[maxm],tt[maxm],ecnt;
int dis[maxn];
int n,m,t;
int que[maxm];
inline void add(int a,int b,int c,int d)
{
vis[ecnt]=0;
cc[ecnt]=c;
tt[ecnt]=d;
to[ecnt]=b;
next[ecnt]=first[a];
first[a]=ecnt++;
vis[ecnt]=0;
cc[ecnt]=c;
tt[ecnt]=d;
to[ecnt]=a;
next[ecnt]=first[b];
first[b]=ecnt++;
return;
}
void init()
{
for(int i=1;i<=n;i++) dis[i]=INF,vis[i]=0;
dis[1]=0;
vis[1]=1;
return;
}
int spfa(int lc) //容量限制
{
int f=0,r=1;
que[f]=1;
init();
while(f!=r)
{
int now=que[f++];
vis[now]=0;
for(int i=first[now];i!=-1;i=next[i])
{
int kid=to[i];
if(cc[i]>=lc && dis[kid]>dis[now]+tt[i])
{
dis[kid]=dis[now]+tt[i];
if(!vis[kid] && dis[kid]<t)
{
vis[kid]=1;
que[r++]=kid;
}
}
}
}
if(dis[n]<=t) return 1;
return 0;
}
void solve()
{
ll f=1,r=INF;
while(f<r)
{
int min=(f+r)/2;
if(spfa(min)) f=min+1;
else r=min-1;
}
if(!spfa(f)) f--;
printf("%d\n",f);
return;
}
int main()
{
// freopen("in.txt","r",stdin);
int cs;
scanf("%d",&cs);
while(cs--)
{
scanf("%d%d%d",&n,&m,&t);
ecnt=0;
memset(first,-1,sizeof(first));
for(int i=0;i<m;i++)
{
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
add(a,b,c,d);
}
solve();
}
return 0;
}