UVA 208 Firetruck (DFS+剪枝)
题意:构造出一张图,给出一个点,字典序输出所有从1到该点的路径
思路:这道题裸搜的话会超时,所以要进行必要的剪枝,刚开始我时用一个dfs从目标点开始搜,dfs能到达的点说明通过这个带你可以到达目标点,这样会超时,所以需要换另一种方法,这里我用的是flody,也可以用并查集。
代码:
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define mod 1000000007
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
const int maxn = 20 + 5, inf = 0x3f3f3f3f;
bool vis[maxn];
int floyd[maxn][maxn];
int d[maxn];
bool G[maxn][maxn];
int n,cnt,Maxn,len;
void print(){
cnt++;
cout<<1;
for(int i = 1 ; i < len ; i ++ ){
cout<<" "<<d[i];
}
cout<<endl;
}
void dfs(int cur,int dd){
if(cur==n){
len = dd;
print();
return;
}
else{
for(int i = 1 ; i <= Maxn ; i ++ ){
if(!vis[i]&&G[cur][i]&&floyd[n][i] != maxn){
d[dd] = i;
vis[i] = true;
dfs(i,dd+1);
vis[i] = false;
}
}
}
}
int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int kase = 1 ;
while(scanf("%d",&n)!=EOF){
memset(G,false,sizeof(G));
memset(vis,false,sizeof(vis));
for(int i = 1 ; i <= 21 ; i ++ )
for(int j = 1 ; j <= 21 ; j ++ )
floyd[i][j] = maxn;
Maxn = 0;
cnt = 0;
printf("CASE %d:\n",kase++);
int a,b;
while(scanf("%d %d",&a,&b)!=EOF&&(a||b)){
G[a][b] = G[b][a] = true;
floyd[a][b] = floyd[b][a] = 1;
if(Maxn < a ) Maxn = a;
if(Maxn < b ) Maxn = b;
}
for (int k = 1; k <= Maxn ; k ++ )
for (int i = 1; i <= Maxn ; i ++ )
for (int j = 1; j <= Maxn ; j ++ )
if (floyd[i][k] + floyd[k][j] < floyd[i][j])
floyd[i][j] = floyd[i][k] + floyd[k][j];
vis[1] = true ;
dfs(1,1);
printf("There are %d routes from the firestation to streetcorner %d.\n",cnt,n);
}
}