图片加载可能有点慢,请跳过题面先看题解,谢谢
\(UVA\)这个\(pdf\)做得真的蠢。。。那张图片把字都盖没了。。。
$
$
又是一道图论水题,快联赛了我还是只会切水题,果然还是太菜了
(话说今天忌装弱。。。)
$
$
不过说实话这道题是真的水,做法也很简单
跑两遍单源最短路,分别求出从起点和从终点出发到每个点最短路
然后直接枚举商业车,对于一条商业车道 \(i\) ,用\(dis1[x]+w[i]+dis2[v]\)或\(dis2[x]+w[i]+dis1[v]\)来更新答案即可
然后就是扣点,对于最短路上的点,一定满足前一个点\(x\)的\(dis\)加上边权等于后一个点\(v\)的\(dis\),就这样\(dfs\)或者\(bfs\)求就行
$
$
//made by Hero_of_Someone
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define N (540)
#define M (2010)
using namespace std;
void File(){freopen(".in","r",stdin);freopen(".out","w",stdout);}
int t,n,S,E,m,K;
int Q[N],k1,k2,sh,cnt;
struct Edge{int u,v,w;}e[M];
int num,head[N],nxt[M],to[M],w[M];
void add(int u,int v,int d){
nxt[++num]=head[u];to[num]=v;w[num]=d;head[u]=num;
nxt[++num]=head[v];to[num]=u;w[num]=d;head[v]=num;
}
void init(){ if(t) puts("");t++;
num=k1=k2=cnt=0;
memset(head,0,sizeof(head));
scanf("%d",&m);
for(int i=1;i<=m;i++){
int u,v,d;
scanf("%d%d%d",&u,&v,&d);
add(u,v,d);
}
scanf("%d",&K);
for(int i=1;i<=K;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
}
bool vis[N];
int dis1[N],dis2[N];
struct node{int x,dis;
bool operator<(const node& a)const{ return dis>a.dis; }
};
priority_queue<node>que;
void Dij(int s,int* dis){
memset(vis,0,sizeof(vis));
que.push((node){s,0}); dis[s]=0;
while(!que.empty()){
node Q=que.top(); que.pop();
int x=Q.x,d=Q.dis;
if(vis[x]) continue;
for(int i=head[x];i;i=nxt[i]){
int v=to[i];
if(dis[v]>dis[x]+w[i]){
dis[v]=dis[x]+w[i];
que.push((node){v,dis[v]});
}
}
vis[x]=1;
}
}
void dfs(int x,int* dis){
Q[++cnt]=x; if(!dis[x]) return ;
for(int i=head[x];i;i=nxt[i]){
int v=to[i];
if(dis[x]==dis[v]+w[i])
dfs(v,dis);
}
}
void work(){
memset(dis1,127/3,sizeof(dis1));
memset(dis2,127/3,sizeof(dis2));
Dij(S,dis1); Dij(E,dis2); sh=dis1[E];
for(int i=1;i<=K;i++){
int u=e[i].u,v=e[i].v,d=e[i].w;
int d1=dis1[u]+d+dis2[v];
int d2=dis2[u]+d+dis1[v];
if(d1<sh) sh=d1,k1=u,k2=v;
if(d2<sh) sh=d2,k1=v,k2=u;
}
if(k1){
dfs(k1,dis1),K=cnt,dfs(k2,dis2);
for(int i=K;i;i--) printf("%d ",Q[i]);
for(int i=K+1;i<cnt;i++) printf("%d ",Q[i]);
printf("%d\n",Q[cnt]);
printf("%d\n",k1);
}
else{
dfs(S,dis2);
for(int i=1;i<cnt;i++) printf("%d ",Q[i]);
printf("%d\n",Q[cnt]);
puts("Ticket Not Used");
}
printf("%d\n",sh);
}
int main(){ while(scanf("%d%d%d",&n,&S,&E)!=EOF){ init(); work(); } return 0; }