题目链接http://ac.jobdu.com/problem.php?pid=1411
转载请注明本文链接http://blog.csdn.net/yangnanhai93/article/details/41315349
这个题目,好难……
这个题目是自己瞎搞弄出来的答案,不知道有没有更优的方法,但是,也说下自己的思路好了
首先明确题目要求,要先从点s出发,然后最短的回到s的路径,所以必然有两种情况
1:出发之后回不来
2:出发之后回来
好吧,确实有点废话,假设第一个到的点为t
则1和2的情况都是求t到s的最短路径,所以只要把从s能达到的点都求一遍最短路径就可以了
但是本题需要注意的问题是
1:在给的有向图中,即边会重复,所以要求一个最短的保存在邻接矩阵中
2:这也是最大的bug,竟然会有s-s的边,这样的话,采用上面的方法就会有点瑕疵了,因为上面的方法会算两遍,所以要先找到可能,把该值作为最短的初始化的值
#include <stdio.h>
#include <memory.h>
using namespace std;
int n,m,s,A[501][501],x,y,z;
bool visited[501];
int INF=2146483647;
int dfs(int x,int s,int n)
{
int dis[501];
for(int i=1;i<=n;i++)
{
dis[i]=A[x][i];
visited[i]=false;
}
visited[x]=true;
int u=x;
for (int i=2;i<=n;i++)
{
int minDis=INF;
for (int j=1;j<=n;j++)
{
if(!visited[j]&&dis[j]<minDis)
{
minDis=dis[j];
u=j;
}
}
visited[u]=true;
for (int j=1;j<=n;j++)
{
if(!visited[j])
{
if(A[u][j]!=INF&&minDis!=INF&&dis[j]>A[u][j]+minDis)
dis[j]=A[u][j]+minDis;
}
}
}
if(dis[s]==INF)
dis[s]=-1;
return dis[s];
//for(int i=1;i<)
}
int min_num(int x,int y)
{
return x>y?y:x;
}
int main()
{
//freopen("data.in","r",stdin);
while(scanf("%d%d%d",&n,&m,&s)!=EOF)
{
int result=INF;
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
A[i][j]=INF;
for (int i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
if(z<A[x][y])
{
A[x][y]=z;
if(x==y&&s==y&&result>z)
result=z;
}
}
for(int i=1;i<=n;i++)
{
if(A[s][i]!=INF)
{
int t=dfs(i,s,n);
if(t!=-1)
result=min_num(result,A[s][i]+t);
}
}
if(result!=INF)
printf("%d\n",result);
else
printf("help!\n");
}
return 0;
}
/**************************************************************
Problem: 1411
User: vincent_ynh
Language: C++
Result: Accepted
Time:710 ms
Memory:2000 kb
****************************************************************/