Legal path
Accepts: 9
Submissions: 171
Time Limit: 6000/3000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
一个有向图,给定起点终点,每条边上有权值。 一条合法的路径定义为相邻边的权值之差不小于K的路径,即路径上每条边的权值至少要比上一条边的权值大K,如果上一条边存在。合法路径的长度定义为路径上的边权值总和。 求从起点到终点的合法路径的最短长度。
输入描述
有多组数据,第一行为数据组数T(T≤10)。 对于每组数据,第一行为三个整数n,m,K,n,m分别表示这组数据的有向图的点数,边数,起点为1号点,终点为n号点。 在接下来有m行,每行有三个整数x,y,z,表示从x到y有一条权值为z的边。 2≤n≤100,000 0≤m≤200,000 1≤K,z≤1,000,000,000 1≤x,y≤n
输出描述
对于每组数据,如果不存在从起点到终点的合法路径,输出-1。 否则输出合法路径的最短长度。
输入样例
3 3 2 1 1 2 1 2 3 2 3 2 1 1 2 2 2 3 1 4 6 2 1 2 1 1 2 2 2 3 3 1 3 5 2 4 2 3 4 7
输出样例
3 -1 11
将所有边按权值排序后问题转化为求一系列边起点为1,终点为n,权值只差>=k,DP轻松解决。这样的想法很好。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<ostream>
#include<istream>
#include<algorithm>
#include<queue>
#include<string>
#include<cmath>
#include<set>
#include<map>
#include<stack>
#include<vector>
#define fi first
#define se second
#define ll long long
#define pii pair<int,ll>
#define P pair<int,int>
#define inf (1ll<<60)
#define eps 1e-8
#define pb push_back
using namespace std;
const int maxn=110005;
int n,m;
ll k;
int x,y;
ll z;
struct Node
{
int from,to;
ll w;
ll tot;
bool operator<(const Node& u)const
{
return w<u.w;
}
}node[maxn*2];
ll d[maxn];
set<ll>se[maxn];
int main()
{
int t;
scanf("%d",&t);
while(t--) {
scanf("%d%d%I64d",&n,&m,&k);
for(int i=1;i<=n;i++) {
d[i]=inf;
se[i].clear();
}
for(int i=1;i<=m;i++) {
scanf("%d%d%I64d",&node[i].from,&node[i].to,&node[i].w);
if(node[i].from==1) {
node[i].tot=node[i].w;
d[node[i].to]=min(d[node[i].to],node[i].w);
}
else
node[i].tot=inf;
}
sort(node+1,node+m+1);
int j=1;
for(int i=1;i<=m;i++) {
while(j<i && node[j].w+k<=node[i].w) {
se[node[j].to].insert(node[j].tot);
j++;
}
if(!se[node[i].from].empty()) {
node[i].tot=min(node[i].tot,*se[node[i].from].begin()+node[i].w);
}
d[node[i].to]=min(d[node[i].to],node[i].tot);
}
if(d[n]==inf)
printf("-1\n");
else
printf("%I64d\n",d[n]);
}
return 0;
}