hdu 2066 一个人的旅行 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2066
最短路 Dijstra
题目分析:求最短路,用dijstra就能做。此题中稍有拐弯的地方是,起止点都不唯一,找最短,应分别分析起止。起点不唯一(不符单源),可以将各起点存为数组,分别求解找最短,亦可构造单源,另设源点(比如设为0,那么其他点的序号是从1开始的,0到各起点距离都为0,本题即采用此种方法);终点不唯一,可以在构造出distance数组后,循环遍历distance[终点i],找到最短从函数返回。
code:
#include<stdio.h>
#define INF 0x7fffffff
int t,s,d,end[1001],max,map[1001][1001],i,j,k;
int dijstra(int sta)
{
bool vis[1001];//以为初值0,懒得再初始化了,结果wrong死
int dis[1001];
//memset(dis,INF,sizeof(dis));//第一处
for(i=0;i<1001;i++)dis[i]=INF,vis[i]=false;//第二处
for(i=0;i<max;i++)
{
dis[i]=map[sta][i];
}
dis[0]=0;
vis[sta]=true;
for(i=0;i<max;i++)
{
int mark=sta,temp=INF;
for(j=1;j<=max;j++)
{
if(!vis[j]&&sta!=j)
{
if(map[sta][j]<INF&&dis[j]>dis[sta]+map[sta][j])
{
//printf("现在应该从 %d 到 %d \n",sta,j);
dis[j]=dis[sta]+map[sta][j];
}
if(dis[j]<temp)
{
//printf("现在的dis[%d]==%d\n",j,dis[j]);
temp=dis[j];
mark=j;
}
}
}
//if(temp==0||temp==INF)break;第三处
vis[mark]=true;
sta=mark;
}
int ans=INF;
for(i=0;i<d;i++)
{
ans=dis[end[i]]<ans?dis[end[i]]:ans;
}
return ans;
}
int main()
{
int a,b,c,i,start,min,flag;
while(scanf("%d%d%d",&t,&s,&d)!=EOF)
{
max=0;
min=INF;
//memset(map,INF,sizeof(map));第一处
for(i=0;i<1001;i++)
{
for(j=0;j<1001;j++)
{
map[i][j]=INF;
}
}
while(t--)
{
scanf("%d%d%d",&a,&b,&c);
if(a>max)max=a;
if(b>max)max=b;
if(map[a][b]>c)
map[a][b]=map[b][a]=c;
}
for(i=0;i<s;i++)
{
scanf("%d",&start);
map[0][start]=0;
}
for(i=0;i<=max;i++)
{
for(j=0;j<=max;j++)
{
//if(map[i][j]<INF)printf("map[%d][%d]==%d\n",i,j,map[i][j]);
}
}
for(i=0;i<d;i++)
{
scanf("%d",&end[i]);
}
//for(k=0;k<s;k++)
{
flag=dijstra(0);
min=min<flag?min:flag;
}
printf("%d\n",min);
}
return 0;
}
以上代码还有几点要说的
第一处:大神指点,memset赋个-1、0、1什么的还行,要想赋infinity,乖乖用for吧……(上一道题就没出现这个问题╮(╯_╰)╭不知道是不是上一个题数组小的原因)
第二处:上网查得bool型变量初值为0(false),结果没初始化,后果可想而知TAT……
第三处:上个题的代码里有这句(模板里抄来的),现在仔细分析一下。这句的意思应该是“如果当前最短路距离为0,或者无穷大,跳出循环”,无穷大时跳出好理解,就是当前点不与任何没走过的点相连,再往下走也找不到路了,用在此题中逻辑也没有问题,所以加上也能A(试过),但距离为0这句就不知为何了,放在此题中是显然不行,因为0与起点的距离是0,加上必wrong。
另外,代码改动较多,也比较难看,为复习时看得到以前的错误,注释都保留下来了,下面是精简版:
#include<stdio.h>
#define INF 0x7fffffff
int t,s,d,end[1001],max,map[1001][1001],i,j;
int dijstra(int sta)
{
bool vis[1001];
int dis[1001];
for(i=0;i<1001;i++)dis[i]=INF,vis[i]=false;
for(i=0;i<max;i++)
{
dis[i]=map[sta][i];
}
dis[0]=0;
vis[sta]=true;
for(i=0;i<max;i++)
{
int mark=sta,temp=INF;
for(j=1;j<=max;j++)
{
if(!vis[j]&&sta!=j)
{
if(map[sta][j]<INF&&dis[j]>dis[sta]+map[sta][j])
{
dis[j]=dis[sta]+map[sta][j];
}
if(dis[j]<temp)
{
temp=dis[j];
mark=j;
}
}
}
if(temp==INF)break;
vis[mark]=true;
sta=mark;
}
int ans=INF;
for(i=0;i<d;i++)
{
ans=dis[end[i]]<ans?dis[end[i]]:ans;
}
return ans;
}
int main()
{
int a,b,c,i,start;
while(scanf("%d%d%d",&t,&s,&d)!=EOF)
{
max=0;
for(i=0;i<1001;i++)
{
for(j=0;j<1001;j++)
{
map[i][j]=INF;
}
}
while(t--)
{
scanf("%d%d%d",&a,&b,&c);
if(a>max)max=a;
if(b>max)max=b;
if(map[a][b]>c)
map[a][b]=map[b][a]=c;
}
for(i=0;i<s;i++)
{
scanf("%d",&start);
map[0][start]=0;
}
for(i=0;i<d;i++)
{
scanf("%d",&end[i]);
}
printf("%d\n",dijstra(0));
}
return 0;
}
PS:将近两天,现在已经是第三天凌晨了,A掉这个题,可以好好睡一觉了……(~ o ~)~zZ