题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2680
思路:反向建图,找到从s到各个出发点所用时间
注意:大水体一枚,卡了2天,倒也发现了自己没注意的地方
说道邻接表在出现重边的时候可以不必考虑,因为在更新的时候只会找到最短的并进行更新,但是前提是。。。要有if的判断
#include<cstdio>
#include<cstring>
using namespace std;
const int num=1005;
const int inf=100000000;
struct node
{
int u,v,next;
}edge[20005];
int n,m,head[num],dis[num],p[num],e;
void add(int a,int b,int c)
{
edge[e].u=b;
edge[e].v=c;
edge[e].next=head[a];
head[a]=e++;
}
void init()
{
int i;
for(i=0;i<=n;i++)
{
p[i]=0;
dis[i]=inf;
}
}
void prim(int s)
{
int i,t,j,tp;
init();
for(i=head[s];i!=-1;i=edge[i].next)
if(dis[edge[i].u]>edge[i].v) //注意此处必须要有if的判断,防重边
dis[edge[i].u]=edge[i].v;
dis[s]=0;
p[s]=1;
for(i=1;i<n;i++)
{
t=inf;
for(j=1;j<=n;j++)
if(p[j]==0&&dis[j]<=t)
{
t=dis[j];
tp=j;
}
p[tp]=1;
for(j=head[tp];j!=-1;j=edge[j].next)
if(p[edge[j].u]==0&&dis[tp]+edge[j].v<dis[edge[j].u])
dis[edge[j].u]=dis[tp]+edge[j].v;
}
}
int main()
{
int i,a,b,c,s,t,ans;
//freopen("in.txt","r",stdin);
while(scanf("%d%d%d",&n,&m,&s)!=EOF)
{
e=0;
memset(head,-1,sizeof(head));
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
add(b,a,c);
}
prim(s);
scanf("%d",&t);
ans=inf;
while(t--)
{
scanf("%d",&a);
if(dis[a]<ans)
ans=dis[a];
}
if(ans<inf)
printf("%d\n",ans);
else
printf("-1\n");
}
return 0;
}
化简又可以避免该问题的方法:
#include<cstdio>
#include<cstring>
using namespace std;
const int num=1005;
const int inf=0x3fffffff;
struct node
{
int v,dis,next;
}edge[20005];
int n,m,head[num],p[num],dis[num],e;
void add(int a,int b,int c)
{
edge[e].v=b;
edge[e].dis=c;
edge[e].next=head[a];
head[a]=e++;
}
void init()
{
int i;
for(i=0;i<=n;i++)
{
dis[i]=inf;
p[i]=0;
}
}
void dij(int src)
{
int i,k,temp,tp;
dis[src]=0;
p[src]=1;
tp=src;
for(i=1;i<=n;i++)
{
for(k=head[tp];k!=-1;k=edge[k].next)
{
if(p[edge[k].v]==0&&dis[tp]+edge[k].dis<dis[edge[k].v])
dis[edge[k].v]=dis[tp]+edge[k].dis;
}
temp=inf;
for(k=1;k<=n;k++)
{
if(p[k]==0&&dis[k]<temp)
{
temp=dis[k];
tp=k;
}
}
p[tp]=1;
}
}
int main()
{
int i,j,a,b,c,t,ans,s;
//freopen("in.txt","r",stdin);
while(scanf("%d%d%d",&n,&m,&s)!=EOF)
{
e=0;
memset(head,-1,sizeof(head));
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
add(b,a,c);
}
init();
dij(s);
scanf("%d",&t);
ans=inf;
while(t--)
{
scanf("%d",&a);
if(dis[a]<ans)
ans=dis[a];
}
if(ans==inf)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}