这个题最开始看标签是最短路,,当时就想的是裸的那啥(d...tra什么玩意),使劲使劲读题才觉得是最小环的问题,,,,,这个也不会呀咱,,,,,也不知道有没有模板,,,所以我就先学习了一下Floyd求最小环。。。。。。。。先讲这个再看题意吧。。哎
这个算法其实,,,,不难理解,,就是A到B的最短路线,,要么是dis(A,B),要么是dis(A,X)+dis(X,B)..就是中间的一个点,,,,,,应该可以算是动态规划的一种情况了,,,,,要说代码,,就是这样的。。。。
for ( k=1; k<=节点个数;++k){
for (i=1;i<=节点个数; ++i ){
for ( j = 1; j <= 节点个数; ++j ){
if ( dis[i][k] + dis[k][j] < dis[i][j] ){
dis[i][j] = dis[i][k] + dis[k][j]; //找到更短路径
}
}
}
}
都不好意思打啊有木有。。。。。。找到所有dis[i][j]的最小值。。。
再说题意。。。找到起点与终点相同的最短路线,,,然后什么十字路口的烦死了有木有啊!!那是什么鬼,,,,,我就把它无视掉了。。。。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int d[101][101]; //储存dp
int q[101][101]; //记录长度
int p[101][101]; //之前的路
int s[101]; //answer
int main()
{
int m,n;
while(scanf("%d",&n)&&n!=-1)
{
scanf("%d",&m);
int i,j,k;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
d[i][j]=q[i][j]=9999999; //全部初始化(不通就是正无穷的大小)
}
d[i][i]=q[i][i]=0; //自己和自己当然零距离
}
memset(p,-1,sizeof(p));
for(i=0;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w); u--,v--; //好放到数组里,,最后加1就好
if(d[u][v]>w&&u!=v) d[u][v]=d[v][u]=q[u][v]=q[v][u]=w; //如果有一次给的距离比之前的要小,由于都是双行道所以果断舍弃之前的啊
p[u][v]=v; p[v][u]=u; //u到v的尽头是v,v到u的尽头是u
}
int ans=9999999,ll,pl;
for(k=0;k<n;k++)
{
for(i=0;i<n;i++) //这个是最小环的判定。。。。。
{
for(j=0;j<n;j++)
{
if(d[i][k]&&d[k][j]&&d[i][k]!=9999999&&d[k][j]!=9999999&&i!=j) //如果i,j,k不是一个点而且通的话(没有那两个!=9999999反而快了。。。)
{
int temp=d[k][i]+q[i][j]+d[j][k]; //计算一个环的距离,,起点终点都是k
if(temp<ans) //不仅要更新数值更要更新路径。。。。
{
ans=temp;
s[0]=k;
ll=0,pl=i; //先是等于从k出去的第一条路
while(pl!=-1)
{
s[++ll]=pl; //记录下来
pl=p[pl][j]; //找下一条路。。。直到前面没有路(回到原点)
}
}
}
}
}
for (int i = 0; i < n; i++) //用的就是那个算法找到ij间的最短距离
{
for (int j = 0; j < n; j++)
{
if (q[i][j] > q[i][k] + q[k][j])
{
q[i][j] = q[i][k] + q[k][j];
p[i][j] = p[i][k]; //让人在记录的时候不至于迷路
}
}
}
}
if (ans == 9999999) printf("No solution.\n");
else
{
for (int i = 0; i < ll; i++)
printf("%d ", s[i] + 1);
printf("%d\n", s[ll] + 1);
}
}
return 0;
}