众所周知,蒜蒜是一名热爱工作的好员工,他觉得时间就是金钱,做事情总是争分夺秒。
这天晚上,蒜蒜一个人去吃晚饭。不巧的是,吃完饭以后就开始下雨了,蒜蒜并没有带雨伞出来。但是蒜蒜热爱工作,工作使他快乐,他要尽快赶回去写代码。
蒜蒜的公司在中关村,中关村这边地形复杂,有很多天桥、地下通道和马路交错在一起。其中,地下通道是可以避雨的,天桥和马路都没办法避。可以把中关村抽象成为 nnn 个点的地图(顶点编号为 111 到 nnn),其中有 m1m_1m1 条地下通道,有 m2m_2m2 条马路或者天桥,其中地下通道的长度为 111。蒜蒜吃饭的地方在 111 点,公司在 nnn 点。当然,蒜蒜虽然爱工作心切,但是他更不想淋很多雨,同时也不想浪费很多时间。于是他折中了一下——在保证他回到公司所走的路程总和小于等于 LLL 的情况下,他希望淋雨的路程和尽量的少。
请你赶紧帮热爱工作的蒜蒜规划一条路径吧,不要再让他浪费时间。
#include<cstdio> #include<queue> #include<vector> #include<cstring> #include<algorithm> using namespace std; const int N=108; const int INF=0x3f3f3f3f; int dp[N][100],n,m1,m2,L; bool vis[N][100]; int head[N],tot; vector<int>G[N]; struct pnp{ int v,w,next; }e[N*N]; void add(int u,int v,int w){ e[tot].v=v,e[tot].w=w,e[tot].next=head[u],head[u]=tot++; } struct node{ int u,id,w; bool operator < (const node &A)const{ return w>A.w; } }; void dij(){ priority_queue<node>Q; dp[1][0]=0; memset(dp,INF,sizeof(dp)); memset(vis,0,sizeof(vis)); node p,q; p.u=1,p.id=0,p.w=0; Q.push(p); while(!Q.empty()){ p=Q.top(); Q.pop(); if(vis[p.u][p.id]) continue; vis[p.u][p.id]=1; for(int i=head[p.u];~i;i=e[i].next){ int v=e[i].v; if(dp[v][p.id]>p.w+e[i].w) { dp[v][p.id]=p.w+e[i].w; q.u=v,q.id=p.id,q.w=dp[v][p.id]; Q.push(q); } } if(p.id==m1) continue; for(int i=0;i<(int)G[p.u].size();++i) { int v=G[p.u][i]; if(dp[v][p.id+1]>p.w+1) { dp[v][p.id+1]=p.w+1; q.u=v,q.id=p.id+1,q.w=dp[v][p.id+1]; Q.push(q); } } } } int main(){ int T,x,y,z; for(scanf("%d",&T);T--;){ memset(head,-1,sizeof(head)); tot=0; for(int i=0;i<=100;++i) G[i].clear(); scanf("%d%d%d%d",&n,&m1,&m2,&L); for(int i=0;i<m1;++i) { scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); } for(int i=0;i<m2;++i) { scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } dij(); int ans=INF; for(int i=0;i<=m1;++i) if(dp[n][i]<=L) ans=min(ans,dp[n][i]-i); printf("%d ",ans==INF?-1:ans); } }