HDU 5168
题意:n个结点的有向图,边带权.定义合法路径为:该路径上的每条边都满足比它前一条至少大k.
合法路径的长度为:该路径上所有边的权值.可能有重边.
n,m<=2e5,k,c[i]<=1e9.问从1->n的最短合法路径.
记录前面一个边的值 然后直接跑SPFA WA....
1
6 7 2
1 2 2
2 3 4
3 4 6
1 5 3
5 4 8
4 6 8
4 6 10
u-v边较小,后面机会可能多,则需要压入队列,但是因为dis[u]+w1>dis[v] 这种情况被忽视了.
注意在压入队列的同时不能更新二元组(dis[v],w1) 因为这两个可能是不同的路径.要更新(dis[u]+w1,w1).
最短路也是可以做的 注意细节 点击打开链接
官方解是DP.
先将所有的边从小到大排序,每次更新(u,v,w)边中的v. 则要知道到当前1-u的"最优"值(1-u路径中边权值+k<=w,否则即使dis[u]此时是最优的,也不能直接走u-v边).
题意:n个结点的有向图,边带权.定义合法路径为:该路径上的每条边都满足比它前一条至少大k.
合法路径的长度为:该路径上所有边的权值.可能有重边.
n,m<=2e5,k,c[i]<=1e9.问从1->n的最短合法路径.
记录前面一个边的值 然后直接跑SPFA WA....
1
6 7 2
1 2 2
2 3 4
3 4 6
1 5 3
5 4 8
4 6 8
4 6 10
u-v边较小,后面机会可能多,则需要压入队列,但是因为dis[u]+w1>dis[v] 这种情况被忽视了.
注意在压入队列的同时不能更新二元组(dis[v],w1) 因为这两个可能是不同的路径.要更新(dis[u]+w1,w1).
最短路也是可以做的 注意细节 点击打开链接
官方解是DP.
先将所有的边从小到大排序,每次更新(u,v,w)边中的v. 则要知道到当前1-u的"最优"值(1-u路径中边权值+k<=w,否则即使dis[u]此时是最优的,也不能直接走u-v边).
则用se[u]来维护:路径中边权值+k<=w时的,1-u的最短路.即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
const ll inf=2e16;
struct node{
int u,v;
ll w,dis;
}e[N];//e[i].dis -> 1->v 's dis (go through u);
int u,v;
ll n,m,k,w,dis[N];
set<ll> se[N];
bool cmp(node a,node b){return a.w<b.w;}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++)
se[i].clear(),dis[i]=inf;
for(int i=1;i<=m;i++)
{
scanf("%d%d%lld",&u,&v,&w);
e[i].u=u,e[i].v=v,e[i].w=w;
if(u==1)
e[i].dis=w,dis[v]=min(dis[v],w);
else
e[i].dis=inf;
}
sort(e+1,e+1+m,cmp);
int j=1;
for(int i=1;i<=m;i++)
{
while(j<i&& e[j].w+k<=e[i].w )
{
se[e[j].v].insert(e[j].dis);
j++;
}
if(!se[e[i].u].empty())
e[i].dis=min(e[i].dis,*se[e[i].u].begin()+e[i].w);
dis[e[i].v]=min(dis[e[i].v],e[i].dis);
}
if(dis[n]==inf)
dis[n]=-1;
cout<<dis[n]<<endl;
}
return 0;
}