热爱工作的蒜蒜
Problem Description
众所周知,蒜蒜是一名热爱工作的好员工,他觉得时间就是金钱,做事情总是争分夺秒。
这天晚上,蒜蒜一个人去吃晚饭。不巧的是,吃完饭以后就开始下雨了,蒜蒜并没有带雨伞出来。但是蒜蒜热爱工作,工作使他快乐,他要尽快赶回去写代码。
蒜蒜的公司在中关村,中关村这边地形复杂,有很多天桥、地下通道和马路交错在一起。其中,地下通道是可以避雨的,天桥和马路都没办法避。可以把中关村抽象成为 n 个点的地图(顶点编号为 1到 n),其中有 m1 条地下通道,有 m2 条马路或者天桥,其中地下通道的长度为 1。蒜蒜吃饭的地方在 1 点,公司在 n 点。当然,蒜蒜虽然爱工作心切,但是他更不想淋很多雨,同时也不想浪费很多时间。于是他折中了一下——在保证他回到公司所走的路程总和小于等于 L 的情况下,他希望淋雨的路程和尽量的少。
请你赶紧帮热爱工作的蒜蒜规划一条路径吧,不要再让他浪费时间。
Input
第一行输入测试组数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的马路或者天桥。
所有路径都是双向的。
Output
对于每组数据,如果有满足要求的路径,输出一个整数,表示淋雨的路程长度,否则输出 −1 。
Sample Input
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
Sample Output
4
5
-1
解题思路:
题目要求的是从1~n的一条路径,满足总路程<=L且淋雨(地上)路程最短,按照这个思路其实就是求一个地上路程的最短路,但这条路要满足总路程<=L的条件。理清思路后,求最短路可以用Dijkstra也可用spfa,只要在入队(加入集合)前判断一下是否能满足总路程<=L就可以了。
Code:
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int maxm=11111;
const int maxn=111;
struct EdgeNode
{
int to;
int w;
int side;//地上为1,地下为0
int next;
};
EdgeNode edges[maxm];
int N,M;
int head[maxn],edge;
bool vis[maxn];
queue <int> que;
int dis[maxn];//记录淋雨(地上)的长度
int total[maxn];//记录总长度
int n,m1,m2,L;
void addedge(int u,int v,int side,int c)
{
edges[edge].side=side;
edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
}
void init()
{
memset(head,-1,sizeof(head));
edge=0;
}
void spfa(int s,int n)//单源最短路(s为起点,n为节点总数)
{
int u;
for (int i=0; i<=n; i++)
{
dis[i]=INF;
total[i]=INF;
}
memset(vis,0,sizeof(vis));
while (!que.empty()) que.pop();
que.push(s);
vis[s]=true;
dis[s]=0;
total[s]=0;
while (!que.empty())
{
u=que.front();
que.pop();
vis[u]=false;
for (int i=head[u]; i!=-1; i=edges[i].next)
{
int v=edges[i].to;
int w=edges[i].w;
int side=edges[i].side;
//总长度小于L,地上距离较小的入队
if (dis[v]>dis[u]+w*side&&total[u]+w<=L)
{
dis[v]=dis[u]+w*side;
total[v]=total[u]+w;
if (!vis[v])
{
vis[v]=true;
que.push(v);
}
}
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d%d%d%d",&n,&m1,&m2,&L);
for(int i=0;i<m1;i++)
{
int a,b;
scanf("%d%d",&a,&b);
addedge(a,b,0,1);
addedge(b,a,0,1);
}
for(int i=0;i<m2;i++)
{
int u,v,c;
scanf("%d%d%d",&u,&v,&c);
addedge(u,v,1,c);
addedge(v,u,1,c);
}
spfa(1,n);
if(dis[n]==INF)
printf("-1\n");
else
printf("%d\n",dis[n]);
}
return 0;
}