这个题目太坑爹。。。昨儿用dfs狂T。
下面先来正确代码 一会儿错误代码也附上 求大神帮我看看dfs 为什么会T 我觉得复杂度一样
T了之后我就看网上说用Bellman_ford算法 也是求单源最短路的算法。但是比dijkstra强的是 图中可以有负权
不过效率真不怎么地 O(n*m)吧
可是我就奇怪的我的dfs也是 这个复杂度啊怎么就T了呢
写完以后还wa了三次 因为没有 每组数据后输出空行 其实我想的是两组之间有一个空行没想到uva居然这样。
我们现在想求最长的路 那换个思维 把路径都变成负的 不就是求最短路了么
这种算法大概就三步
第一个初始化d数组 除了源点意外都设为inf 不可达
第二步开始循环每条边。一共循环最多n-1 次 至于为什么 想下如果这个图没有环 那源点到任何一个点最多用n-1步就到了么 跟MST一个道理。。
每次循环的是边 对于每条边 (u,v,w);
如果的d[u]!=inf 也就是说已经到过这个点了。 并且 d【u】+w
那么就更新dv 网上称这种更新为 松弛。
这样完成后 就得到了 虽然本题不需要 但是还是要考虑一下如果这个全存在回路呢?
如果这个回路权值是正的 也就是说整条回路权值总和大于0 那么一定不会在这里死循环。
如果回路权值是负的 那就麻烦了。每次更新的时候都会成功,这样一个点一定会一直减小。
那么怎么判断呢?
也就是说 如果没有负权回路上面循环每一条边一定不可能再更新的。
这样这个算法就描述完成了 还有可以设置一个 ischanged 如果某次没有变化 那下次也还是不会变 直接break了 这样就是 说明最短路径已经查找完毕,或者部分点不可达,跳出循环。否则执行下次循环;
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=105;
const int inf=1<<15;
int n,s;
int map[maxn][maxn];
int d[maxn];
void Bellman_ford()
{
//第一次写Bellman_ford 首先要初始化d数组
int i,j,k;
for(i=1;i<=n;++i)
d[i]=inf;
d[s]=0;
bool ischanged=1;
for(k=1;k<n && ischanged;++k)//最多松弛n-1次 因为一共n个点 如果没有回路 s到任何一个点做多n-1条边
{
ischanged=0;
for(i=1;i<=n;++i)
{
for(j=1;j<=n;++j)
{
if(map[i][j]!=0 && d[i]!=inf && d[i]+map[i][j]<d[j])
{
ischanged=1;
d[j]=d[i]+map[i][j];
}
}
}
}
}
int main()
{
int i,j,a,b,ca=1;
while(scanf("%d",&n),n)
{
scanf("%d",&s);
memset(map,0,sizeof(map));
memset(d,0,sizeof(d));
while(scanf("%d%d",&a,&b),a+b)
{
map[a][b]=-1;
}
Bellman_ford();
int ans=10000,index;
for(i=1;i<=n;++i)
{
if(d[i]<ans)
{
ans=d[i];
index=i;
}
}
printf("Case %d: The longest path from %d has length %d, finishing at %d.\n\n",ca++,s,-ans,index);
}
return 0;
}
/* dfs方法! 尼玛T了!!!
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=105;
int n,s;
int map[maxn][maxn];
int len[maxn];
inline void in(int &a)
{
char ch;
while(ch = getchar(), ch < '0' || ch > '9');
a = ch - '0';
while(ch = getchar(), ch >= '0' && ch <= '9')
{
a = a * 10 + ch - '0';
}
return;
}
void dfs(int v)
{
for(int i=1;i<=n;++i)
{
if(map[v][i])
{
if(len[v]+1>len[i])
len[i]=len[v]+1;
dfs(i);
}
}
}
int main()
{
int i,j,a,b,ca=1;
while(true)
{
in(n);
if(n==0) break;
in(s);
memset(map,0,sizeof(map));
memset(len,0,sizeof(len));
while(true)
{
in(a);
in(b);
if(a==0 && b==0) break;
map[a][b]=1;
}
dfs(s);
int ans=-1,index;
for(i=1;i<=n;++i)
{
if(len[i]>ans)
{
ans=len[i];
index=i;
}
}
if(ca!=1)
printf("\n");
printf("Case %d: The longest path from %d has length %d, finishing at %d.\n",ca++,s,ans,index);
}
return 0;
}*/