回溯。时间复杂度是阶乘级的,需要剪枝。
加了两个剪枝,这两个剪枝都依赖于Floyd算法。
先通过Floyd算法求出dis[i][j]表示i到j之间简单路径的条数。
然后在回溯选择边的时候,需要看该点到n点是否有路径,没有则说明该点不能到n,所以可以剪掉。
另外当输出个数达到dis[1][n]的时候就可以直接结束了,不需要继续递归了。
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define MAXN 30
using namespace std;
bool vis[MAXN],gl[MAXN][MAXN];
bool no[MAXN];
int ans[MAXN],dis[MAXN][MAXN];
int n,T,cnt,N;
void dfs(int pos,int d)
{
if(cnt==N) return ;
if(pos==n)
{
cnt++;
for(int i=1; i<=d; ++i)
if(i==1) printf("%d",1);
else printf(" %d",ans[i]);
printf("\n",n);
return ;
}
else
{
for(int i=1; i<=T; ++i)
{
if(gl[pos][i]&&!vis[i]&&dis[i][n])
{
vis[i]=true;
ans[d+1]=i;
dfs(i,d+1);
vis[i]=false;
}
}
}
}
int main()
{
int kase=0;
ans[1]=1;
while(scanf("%d",&n)!=EOF)
{
int u,v;
memset(gl,0,sizeof(gl));
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
T=0;
while(scanf("%d%d",&u,&v)&&!(!u&&!v))
{
gl[u][v]=gl[v][u]=true;
dis[u][v]=dis[v][u]=1;
T=max(T,max(u,v));
}
for(int k=1; k<=T; ++k)
for(int i=1; i<=T; ++i)
for(int j=1; j<=T; ++j)
dis[i][j]+=dis[i][k]*dis[k][j];
N=dis[1][n];
cnt=0;
printf("CASE %d:\n",++kase);
vis[1]=true;
dfs(1,1);
printf("There are %d routes from the firestation to streetcorner %d.\n",cnt,n);
}
return 0;
}