题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=1
记录路径不会,于是又拜访了一下各个牛人的博客,真是惭愧。。无奈牛人都是用DP做的。。。sad。。。好不容易找到一个用spfa做的,写的乱七八糟。。不不。。是写的很高级,连加边都写得那么高级,实在看不懂,。不过有了思路。于是现学的spfa。。记录路径其实就是在松弛的过程中记录路径。然后在最后最短路求完后再回溯,把路径求出来。然后输出即可。这题调试了好长时间。。。终于调试成功了。。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include<algorithm>
using namespace std;
int n, m, vis[200], d[200], head[200], maxint=0,p[200], per[200],lu[200], cnt;
struct node
{
int v, w, next;
}edge[10000];
void add(int u, int v, int w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
}
void spfa(int s)
{
int i;
queue<int>q;
for(i=0;i<=n;i++)
d[i]=maxint;
d[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty())
{
int f=q.front();
q.pop();
vis[f]=0;
for(i=head[f];i!=-1;i=edge[i].next)
{
if(d[edge[i].v]<edge[i].w+d[f])
{
d[edge[i].v]=edge[i].w+d[f];
//printf("%d %d\n",edge[i].v,d[edge[i].v]);
per[edge[i].v]=f;
//printf("%d %d\n",edge[i].v,f);
if(!vis[edge[i].v])
{
vis[edge[i].v]=1;
q.push(edge[i].v);
}
}
}
}
}
int main()
{
int t, i, a, b, num=0, j;
scanf("%d",&t);
while(t--)
{
num++;
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
memset(edge,0,sizeof(edge));
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&p[i]);
}
p[++n]=p[1];
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&a,&b);
if(a>b)
{
int t=a;
a=b;
b=t;
}
add(a,b,p[b]);
}
cnt=0;
spfa(1);
printf("CASE %d#\n",num);
printf("points : %d\n",d[n]);
printf("circuit : 1");
cnt=0;
/*for(i=1;i<=n;i++)
printf("%d ",per[i]);
printf("\n");*/
for(j=per[n];j!=1;j=per[j])
{
lu[cnt++]=j;
}
for(j=cnt-1;j>=0;j--)
{
printf("->%d",lu[j]);
}
printf("->1\n");
if(t!=0)
printf("\n");
}
return 0;
}