#include<bits/stdc++.h>
using namespace std;
int dp[1005],V[1005];
int MAP[1005][1005];
const int inf=0x3f3f3f3f;
int minhh(int x,int y)
{
if(x<=y)return x;
else return y;
}
int main()
{
int i,n,m,s,min,a,b,w[1005];
while(scanf("%d %d %d",&n,&m,&s)!=EOF)
{
memset(MAP,inf,sizeof(MAP));
for(i=1;i<=n;i++)MAP[i][i]=0;
while(m--)
{
scanf("%d %d %d",&a,&b,&i);
MAP[b][a]=minhh(MAP[b][a],i);
//MAP[b][a]=MAP[a][b];
//注意这里是本题是有向图,所以利用反向图思路是,输入数据路线的起点和终点也要反向
}
scanf("%d",w);
for(i=1;i<=w[0];i++)scanf("%d",&w[i]);
//录入题给信息
memset(dp,inf,sizeof(dp));
memset(V,-1,sizeof(V));
for(i=1;i<=n;i++)dp[i]=MAP[s][i];//反向图,起点当终点,终点当起点,变为单源多终点问题
while(1)
{
dp[1003]=inf;min=1003;m=0;//初始化
for(i=1;i<=n;i++)
{
if(V[i]==-1&&dp[i]<dp[min])min=i;
}//找出最小边
for(a=1;a<=w[0];a++)if(min==w[a]){m=-1;break;}
if(m==-1)break;
if(min==1003)break;//所有路径都考虑完了
V[min]=0;//表示这个城市考虑过了
for(i=1;i<=n;i++)
{
if(V[i]==-1&&dp[i]>dp[min]+MAP[min][i])
dp[i]=dp[min]+MAP[min][i];
}//松弛操作,更新到达每个城市的最短路径
}
if(dp[min]>=inf)printf("-1\n");
else printf("%d\n",dp[min]);
}
return 0;
}
总结 :
1.这题是多起点单个终点的有向图,直接DJ会超时,可以使用反向图(起点当终点,终点当起点,变成单起点多终点问题)或者自己再加上一个到各个起点距离都为0的新起点,变成单起点单终点问题,以此简化运算,提高效率
2.对于有向图用反向图思路解题时,要注意输入路线数据时的起点和终点也要反向
直接多起点硬解案例(会超时)
#include<bits/stdc++.h>
using namespace std;
int dp[1005],V[1005];
int MAP[1005][1005];
const int inf=0x3f3f3f3f;
int minhh(int x,int y)
{
if(x<=y)return x;
else return y;
}
int main()
{
int i,n,m,s,min,minn,a,b,w[1005];
while(scanf("%d %d %d",&n,&m,&s)!=EOF)
{
memset(MAP,inf,sizeof(MAP));
for(i=1;i<=n;i++)MAP[i][i]=0;
while(m--)
{
scanf("%d %d %d",&a,&b,&i);
MAP[a][b]=minhh(MAP[a][b],i);
//MAP[b][a]=MAP[a][b];
}
scanf("%d",w);
for(i=1;i<=w[0];i++)scanf("%d",&w[i]);
//录入题给信息
minn=inf;
for(a=1;a<=w[0];a++)
{
memset(dp,inf,sizeof(dp));
memset(V,-1,sizeof(V));
for(i=1;i<=n;i++)dp[i]=MAP[w[a]][i];
while(1)
{
dp[1003]=inf;min=1003;m=0;//初始化
for(i=1;i<=n;i++)
{
if(V[i]==-1&&dp[i]<dp[min])min=i;
}//找出最小边
if(min==s)break;
if(min==1003)break;//所有路径都考虑完了
V[min]=0;//表示这个城市考虑过了
for(i=1;i<=n;i++)
{
if(V[i]==-1&&dp[i]>dp[min]+MAP[min][i])
dp[i]=dp[min]+MAP[min][i];
}//松弛操作,更新到达每个城市的最短路径
}
minn=minhh(dp[min],minn);
}//考虑不同起点的最短路径,找出最小的
if(minn>=inf)printf("-1\n");
else printf("%d\n",minn);
}
return 0;
}