这竟然是一道Final题。
题目大意,给出n条边,然后让你把1到一个指定的终点ep的所有可行路径输出出来,每个点最多只能经过一次。
解法:DFS即可,但是紫书上面说这题裸搜是过不去的,会tle,要先判断一下1到ep是否连通,那我就用个并查集看看就好了。一开始还以为按照VJ上面这道题的PDF的输出那样输出,然后PE了,看了看好像题目只说了要输出路径而已,那么就正常输出好了。
代码如下:
#include<bits/stdc++.h>
using namespace std;
int vst[25], ans[25], ep, cnt, father[25];
vector <int> edge[25];
void dfs(int s, int k) {
if(s == ep) {
// printf(" ");
for(int i = 0; i < k; i++) {
printf("%d%c", ans[i], i == k - 1 ? '\n' : ' ');
}
cnt++;
return;
}
for(int i = 0; i < edge[s].size(); i++) {
int v = edge[s][i];
if(!vst[v]) {
vst[v] = 1;
ans[k] = v;
dfs(v, k + 1);
vst[v] = 0;
}
}
}
bool dfs_k(int s) {
if(s == ep) {
return 1;
}
for(int i = 0; i < edge[s].size(); i++) {
int v = edge[s][i];
if(!vst[v]) {
vst[v] = 1;
if(dfs_k(v))
return 1;
vst[v] = 0;
}
}
return 0;
}
int Find(int x) {
int root, tmp = x;
while(father[x] != x) {
x = father[x];
}
root = x;
x = tmp;
while(father[x] != x) {
tmp = father[x];
father[x] = root;
x = tmp;
}
return root;
}
void Union(int u, int v) {
u = Find(u);
v = Find(v);
father[v] = u;
}
void init() {
for(int i = 0; i < 25; i++) {
edge[i].clear();
father[i] = i;
}
cnt = 0;
}
int main() {
int Case = 1, u, v;
while(cin >> ep) {
init();
while(cin >> u >> v) {
if(u == v && u == 0)
break;
if(Find(u) != Find(v))
Union(u, v);
edge[u].push_back(v);
edge[v].push_back(u);
}
for(int i = 0; i < 25; i++)
sort(edge[i].begin(), edge[i].end());
printf("CASE %d:\n", Case++);
vst[1] = 1;
ans[0] = 1;
if(Find(1) == Find(ep))
dfs(1, 1);
printf("There are %d routes from the firestation to streetcorner %d.\n", cnt, ep);
}
return 0;
}