题目链接:https://cn.vjudge.net/problem/UVA-11374
思路:找出起点到每个点的距离,再找出每个点到终点的距离,枚举商业线的两个点。
wa点:枚举商业线的时候不能只把前一个点当起点,后一个点当终点,路是双向的,两个点都有可以当作与起点相连的点。
#include<algorithm>
#include<string.h>
#include<stdio.h>
using namespace std;
struct node
{
int y,v,nextt;
} A[10000];
int n,s,m,x,y,v,cut,e;
int head[1000],vis[1000],dis1[1000],dis2[1000],path[1000],re[1000];
void init()
{
memset(head,-1,sizeof(head));
cut=0;
return ;
}
void add(int x,int y,int v)
{
A[cut].y=y;
A[cut].v=v;
A[cut].nextt=head[x];
head[x]=cut++;
return ;
}
int dijskl(int s,int *ans)
{
memset(vis,0,sizeof(vis));
memset(ans,0x3f,sizeof(int)*(n+5));
ans[s]=0;
int k,pan;
for(int k1=1; k1<=n; k1++)
{
pan=0x3f3f3f3f,k=-1;
for(int i=1; i<=n; i++)
{
if(vis[i]==0&&ans[i]<pan)
{
pan=ans[i];
k=i;
}
}
if(k==-1)
break;
vis[k]=1;
for(int i=head[k]; i!=-1; i=A[i].nextt)
{
if(ans[A[i].y]>ans[k]+A[i].v)
{
path[A[i].y]=k;
ans[A[i].y]=ans[k]+A[i].v;
}
}
}
return 0;
}
void see(int *an)
{
for(int i=1;i<=n;i++)
printf("%d ",an[i]);
printf("\n");
}
int main()
{
int qq=0;
while(~scanf("%d%d%d",&n,&s,&e))
{
if(qq)
printf("\n");
qq++;
scanf("%d",&m);
init();
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&x,&y,&v);
add(x,y,v);
add(y,x,v);
}
dijskl(s,dis1);
dijskl(e,dis2);
scanf("%d",&m);
int jix=-1,jiy=-1,jiv=-1,pan=dis1[e],carry=0;
for(int i=1; i<=m; i++)
{
scanf("%d%d%d",&x,&y,&v);
if(dis1[x]+dis2[y]+v<pan)
{
pan=dis1[x]+dis2[y]+v;
jix=x;
jiy=y;
jiv=v;
}
if(dis1[y]+dis2[x]+v<pan)
{
pan=dis1[y]+dis2[x]+v;
jix=y;
jiy=x;
jiv=v;
}
}
add(jix,jiy,jiv);
add(jiy,jix,jiv);
memset(path,-1,sizeof(path));
dijskl(e,dis1);
printf("%d",s);
while(s!=e)
{
printf(" %d",path[s]);
s=path[s];
}
if(jix==-1)
printf("\nTicket Not Used\n");
else
printf("\n%d\n",jix);
printf("%d\n",pan);
}
return 0;
}