众所周知,蒜蒜是一名热爱工作的好员工,他觉得时间就是金钱,做事情总是争分夺秒。
这天晚上,蒜蒜一个人去吃晚饭。不巧的是,吃完饭以后就开始下雨了,蒜蒜并没有带雨伞出来。但是蒜蒜热爱工作,工作使他快乐,他要尽快赶回去写代码。
蒜蒜的公司在中关村,中关村这边地形复杂,有很多天桥、地下通道和马路交错在一起。其中,地下通道是可以避雨的,天桥和马路都没办法避。可以把中关村抽象成为 n 个点的地图(顶点编号为 1 到 n),其中有 m1 条地下通道,有 m2 条马路或者天桥,其中地下通道的长度为 1。蒜蒜吃饭的地方在 1 点,公司在 n 点。当然,蒜蒜虽然爱工作心切,但是他更不想淋很多雨,同时也不想浪费很多时间。于是他折中了一下——在保证他回到公司所走的路程总和小于等于 L 的情况下,他希望淋雨的路程和尽量的少。
请你赶紧帮热爱工作的蒜蒜规划一条路径吧,不要再让他浪费时间。
输入格式
第一行输入测试组数 T(1≤T≤20)。
接下来 T 组数据。
每一组数据的第一行输入四个整数 n(2≤n≤100),m1(0≤m1≤50),m2(0≤m2≤5000),L(1≤L≤108)。
接下里 m1 行,每行输入两个整数 a, b(1≤a,b≤n),表示 a 和 b 之间有一条地下通道。
接下里 m2 行,每行输入三个整数 u,v(1≤u,v≤n),c(1≤c≤106),表示 u 和 v 之间有一条长度为 c 的马路或者天桥。
所有路径都是双向的。
输出格式
对于每组数据,如果有满足要求的路径,输出一个整数,表示淋雨的路程长度,否则输出 -1。
样例输入
3 4 2 2 6 1 2 2 3 1 4 5 3 4 4 4 2 2 5 1 2 2 3 1 4 5 3 4 4 4 2 2 4 1 2 2 3 1 4 5 3 4 4
样例输出
4 5 -1
思路:用d[i][j]表示到达i点且走了j条地下通道时,淋雨路程的最小值。然后用求最短路的方式转移。
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e4;
struct lenka
{
int to;
long long w1,w2;
int operator<(const lenka& x)const{return x.w2<w2;}
};
struct edg
{
int to,next;
long long c1,c2;
}ed[MAX*2];
int head[101],tot=0;
void add(int x,int y,long long z,int tag)
{
ed[tot].to=y;
ed[tot].c1=ed[tot].c2=0;
if(tag)ed[tot].c1=1;
else ed[tot].c2=z;
ed[tot].next=head[x];
head[x]=tot++;
}
long long d[101][61];
int v[101][61],L,n,m1,m2;
void spfa()
{
priority_queue<lenka>p;
p.push((lenka){1,0,0});
memset(v,0,sizeof v);
memset(d,0x3f,sizeof d);
d[1][0]=0;
long long ans=1e9+7;
while(!p.empty())
{
lenka now=p.top();p.pop();
if(now.to==n&&now.w1+now.w2<=L)ans=min(ans,now.w2);
if(v[now.to][now.w1])continue;
v[now.to][now.w1]=1;
for(int i=head[now.to];i!=-1;i=ed[i].next)
{
int nex=ed[i].to;
if(ed[i].c1&&now.w1<m1&&d[nex][now.w1+1]>now.w2)
{
d[nex][now.w1+1]=now.w2;
p.push((lenka){nex,now.w1+1,now.w2});
}
else if(ed[i].c2&&d[nex][now.w1]>now.w2+ed[i].c2)
{
d[nex][now.w1]=now.w2+ed[i].c2;
p.push((lenka){nex,now.w1,d[nex][now.w1]});
}
}
}
if(ans==1e9+7)cout<<-1<<endl;
else cout<<ans<<endl;
}
int main()
{
int T;cin>>T;
while(T--)
{
cin>>n>>m1>>m2>>L;
memset(head,-1,sizeof head);
tot=0;
for(int i=0;i<m1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y,1,1);
add(y,x,1,1);
}
for(int i=0;i<m2;i++)
{
int x,y;
long long z;
scanf("%d%d%lld",&x,&y,&z);
add(x,y,z,0);
add(y,x,z,0);
}
spfa();
}
return 0;
}