跑两次Dijkstra算法。
第二次以终点为起点,这样枚举每一条可换权值的边,即可找出最小值。
Dijkstra用的O(nlogn)的堆优化的算法。
另外,在输出时应注意格式,如果该组数据是最后一组就不能在行末换行,否则会PE。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=555;
int n,s,t,m;
struct data{int to,next,vi;}e[maxn*4];
int head[maxn];
int cnt=0;
int diss[maxn];
int dist[maxn];
void ins(int u,int v,int w)
{
e[++cnt].to=v;
e[cnt].next=head[u];
e[cnt].vi=w;
head[u]=cnt;
}
struct heap
{
int d,uu;
bool operator < (const heap& x)const{return d>x.d;}
};
bool vis[maxn];
void dijs()
{
priority_queue<heap> q;
memset(diss,63,sizeof(diss));
diss[s]=0;
memset(vis,0,sizeof(vis));
q.push((heap){0,s});
while(!q.empty())
{
heap u=q.top();q.pop();
int x=u.uu;
if(vis[x])continue;
vis[x]=1;
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(diss[v]>diss[x]+e[i].vi)
{
diss[v]=diss[x]+e[i].vi;
q.push((heap){diss[v],v});
}
}
}
}
void dijt()
{
priority_queue<heap> q;
memset(dist,63,sizeof(dist));
dist[t]=0;
memset(vis,0,sizeof(vis));
q.push((heap){0,t});
while(!q.empty())
{
heap u=q.top();q.pop();
int x=u.uu;
if(vis[x])continue;
vis[x]=1;
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(dist[v]>dist[x]+e[i].vi)
{
dist[v]=dist[x]+e[i].vi;
q.push((heap){dist[v],v});
}
}
}
}
int dis[maxn];
void dij()
{
priority_queue<heap> q;
memset(dis,63,sizeof(dis));
dis[s]=0;
memset(vis,0,sizeof(vis));
q.push((heap){0,s});
while(!q.empty())
{
heap u=q.top();q.pop();
int x=u.uu;
if(vis[x])continue;
vis[x]=1;
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(dis[v]>dis[x]+e[i].vi)
{
dis[v]=dis[x]+e[i].vi;
q.push((heap){dis[v],v});
}
}
}
}
int p[maxn];
int top=0;
void bfs(int x)
{
p[++top]=x;
for(int i=head[x];i;i=e[i].next)
{
int u=e[i].to;
if(dis[u]==dis[x]-e[i].vi)bfs(u);
}
}
int main()
{
ios::sync_with_stdio(0);cin.tie(0);
int sce=0;
while(cin>>n>>s>>t>>m)
{
sce++;
if(sce>1)cout<<endl;
memset(e,0,sizeof(e));
memset(head,0,sizeof(head));
cnt=top=0;
int x,y,z;
for(int i=1;i<=m;i++)
{
cin>>x>>y>>z;
ins(x,y,z);
ins(y,x,z);
}
dijs();dijt();
int k;
cin>>k;
int ans=1e9+10;
int pos;
int a,b,c;
for(int i=1;i<=k;i++)
{
cin>>x>>y>>z;
if(ans>diss[x]+dist[y]+z)
{
ans=diss[x]+dist[y]+z;
pos=x;
a=x,b=y,c=z;
}
if(ans>diss[y]+dist[x]+z)
{
ans=diss[y]+dist[x]+z;
pos=y;
a=x,b=y,c=z;
}
}
for(int i=1;i<=n;i++)if(diss[i]+dist[i]<ans)
{
ans=diss[i]+dist[i];
pos=0;
}
if(pos!=0)ins(a,b,c),ins(b,a,c);
dij();bfs(t);
for(int i=top;i>1;i--)cout<<p[i]<<" ";
cout<<p[1]<<endl;
if(pos)cout<<pos<<endl;
else cout<<"Ticket Not Used"<<endl;
cout<<ans<<endl;
}
return 0;
}