题目大意:给定节点树不超过20的图,图的节点已数字标识,再给定某个节点的序号,求从节点1到节点k的所有路径,以字典序排序。
这一题 的关键在于 需要先判断是否能够从节点1到达节点k,也就是使用并查集来判断,同时也需要去除那些不能够到达k的点,这就是剪枝,否则这题会超时。
//
// main.cpp
// uva 208 - Firetruck
//
// Created by XD on 15/7/30.
// Copyright (c) 2015年 XD. All rights reserved.
//
#include <iostream>
#include <string>
#include <queue>
#include <stack>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include<vector>
#include <string.h>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cstdio>
using namespace std ;
int flag[21] ;
int g[21][21] ;
int n , k ;
int p[21] ;
int r[21] ;
int num ;
void init()
{
memset(flag, 0, sizeof(flag)) ;
memset(g, 0, sizeof(g)) ;
for (int i = 0; i < 21; i++) {
p[i] = i ;
r[i] = 0 ;
}
}
int find(int x)
{
if (p[x]!=x) {
p[x] = find(p[x]) ;
}
return p[x] ;
}
void link(int x ,int y )
{
if (r[x] < r[y]) {
p[x] =y ;
}
else{
p[y] = x ;
if (r[x] == r[y]) {
r[x]+= 1 ;
}
}
}
void UNION_SET(int x , int y )
{
link(find(x), find(y)) ;
}
int max(int i , int j )
{
return i > j ? i : j ;
}
int path[20] ;
void dfs(int u,int d )
{
if (u == k ) {
printf("1" ) ;
int i = 2 ;
num++ ;
for (i = 1; i < d; i++) {
printf(" %d" ,path[i]) ;
}
printf("\n") ;
return ;
}
for (int i = 1; i <= n ; i++) {
if (!flag[i] && g[u][i]) {
flag[i]=1 ;
path[d] = i ;
dfs(i , d+1) ;
flag[i] = 0 ;
}
}
}
int main() {
int casenum = 0 ;
while (scanf("%d" ,&k)==1) {
num = 0 ;
n = 0 ;
int v ,u ;
init() ;
printf("CASE %d:\n" , ++casenum) ;
while (scanf("%d%d" ,&v , &u)==2&&u+v!= 0 ) {
n = max(n,max(u,v)) ;
g[u][v] = g[v][u] =1 ;
if (find(u)!= find(v)) {
UNION_SET(u, v) ;
}
}
for (int i = 1; i <=n;i++) {
find(i) ;
}
for (int i = 1; i <=n; i++) {
if (p[k] != p[i]) {
flag[i] = 1 ;
}
}
if (flag[1]) {
printf("There are 0 routes from the firestation to streetcorner %d.\n" , k) ;
}
else{
flag[1] = 1 ;
path[0] = 1 ;
dfs(1,1) ;
printf("There are %d routes from the firestation to streetcorner %d.\n" ,num, k) ;
}
}
return 0;
}