UVA - 208 Firetruck(消防车)(并查集+回溯)

题意:输入着火点n,求结点1到结点n的所有路径,按字典序输出,要求结点不能重复经过。

分析:用并查集事先判断结点1是否可以到达结点k,否则会超时。dfs即可。

#pragma comment(linker, "/STACK:102400000, 102400000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#define Min(a, b) ((a < b) ? a : b)
#define Max(a, b) ((a < b) ? b : a)
typedef long long ll;
typedef unsigned long long llu;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int MOD = 1e9 + 7;
const double pi = acos(-1.0);
const double eps = 1e-8;
const int MAXN = 30 + 10;
const int MAXT = 10000 + 10;
using namespace std;
int fa[MAXN];
int pic[MAXN][MAXN];
int vis[MAXN];
int ans[MAXN];
int cnt;
int n;
int Find(int v){
    return fa[v] = (fa[v] == v) ? v : Find(fa[v]);
}
void dfs(int cur){
    if(ans[cur] == n){
        ++cnt;
        for(int i = 1; i <= cur; ++i){
            if(i != 1) printf(" ");
            printf("%d", ans[i]);
        }
        printf("\n");
    }
    else{
        for(int i = 1; i <= 21; ++i){
            if(pic[ans[cur]][i] && !vis[i]){
                vis[i] = 1;
                ans[cur + 1] = i;
                dfs(cur + 1);
                vis[i] = 0;
            }
        }
    }
}
int main(){
    int kase = 0;
    while(scanf("%d", &n) == 1){
        int x, y;
        memset(pic, 0, sizeof pic);
        memset(vis, 0, sizeof vis);
        memset(ans, 0, sizeof ans);
        cnt = 0;
        for(int i = 0; i < MAXN; ++i){
            fa[i] = i;
        }
        while(scanf("%d%d", &x, &y) == 2){
            if(!x && !y) break;
            pic[x][y] = 1;
            pic[y][x] = 1;
            int tx = Find(x);
            int ty = Find(y);
            if(tx < ty) fa[ty] = tx;
            else if(tx > ty) fa[tx] = ty;
        }
        printf("CASE %d:\n", ++kase);
        if(Find(n) != 1){
            printf("There are 0 routes from the firestation to streetcorner %d.\n", n);
            continue;
        }
        vis[1] = 1;
        ans[1] = 1;
        dfs(1);
        printf("There are %d routes from the firestation to streetcorner %d.\n", cnt, n);
    }
    return 0;
}
时间: 2024-10-24 13:34:08

UVA - 208 Firetruck(消防车)(并查集+回溯)的相关文章

UVA 10158 War(并查集)

War A war is being lead between two countries, A and B. As a loyal citizen of C, you decide to help your country's espionage by attending the peace-talks taking place these days (incognito, of course). There are n people at the talks (not including y

uva 10608 Friends(并查集)

uva 10608 Friends 题目大意:给出两两之间的关系,求出最大的关系网. 解题思路:并查集裸体. #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <cstdlib> using namespace std; const int N = 30005; typedef long long ll; int n, m; in

uva 12232 - Exclusive-OR(加权并查集)

题目链接:uva 12232 - Exclusive-OR 题目大意:有n个数,一开始并不知道具体的值,现在进行Q次操作. I u k:au的值为k I u v k:au?av=k Q k q1q2-qk:求q1?q2-?qk 对于Q操作不能确定的话输出"I don't know." 对于I操作矛盾的话则输出是第几条I操作出现矛盾的,并且停止后面所有的操作. 解题思路:加权并查集,f[x]表示x节点父亲节点,d[x]表示x节点与其父节点的亦或值,对于确定的节点值,可以将父亲节点设为0,

UVA 11987 - Almost Union-Find(并查集)

UVA 11987 - Almost Union-Find 题目链接 题意:给定一些集合,操作1是合并集合,操作2是把集合中一个元素移动到另一个集合,操作3输出集合的个数和总和 思路:并查集,关键在于操作2,对于并查集,要去除掉一个结点,如果该结点不是根那就好办了,那么就多开n个结点,每个结点初始父亲都是它的i + n,这样在移动的时候,就不用担心他是根结点了剩下就是普通的带权并查集了 代码: #include <cstdio> #include <cstring> const i

UVA 10608 Friends【并查集】

题目链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1549 题意:给定n个人m种朋友关系,求最大朋友圈的人数.裸并查集 代码: #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm>

Connect the Campus (Uva 10397 Prim || Kruskal + 并查集)

题意:给出n个点的坐标,要把n个点连通,使得总距离最小,可是有m对点已经连接,输入m,和m组a和b,表示a和b两点已经连接. 思路:两种做法.(1)用prim算法时,输入a,b.令mp[a][b]=0.然后进行一遍prim(2)Kruskal算法+并查集 代码: //prim写法 #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <

UVA - 1197 (简单并查集计数)

Severe acute respiratory syndrome (SARS), an atypical pneumonia of unknown aetiology, was recognized as a global threat in mid-March 2003. To minimize transmission to others, the best strategy is to separate the suspects from others. In the Not-Sprea

UVa 208 Firetruck【回溯】

题意:给出一个n个节点的无向图,以及某个节点k,按照字典序从小到大输出从节点1到节点k的所有路径 看的题解 http://blog.csdn.net/hcbbt/article/details/9755147 因为节点数很少(小于20),所以可以先用floyd处理一下,判断一点是否能够到达终点 然后就像紫书里面枚举排列那样的去挨个找出字典序从小到大的路径 题解里面说到的无回溯的走遍和终点相连的所有点,他写的代码是判断的d[en][i],判断终点到i点是否可达 写成d[i][en]也能过,因为是无

(判连通+暴力)UVA - 208 Firetruck

原题链接: 比较麻烦,就不挂,可以上uva live找,也可以用virtual judge挂题. 题意: 输出从1到k的所有路径,不能重复经过 分析: 这题就是简单的深搜回溯,用一个数组记录路径,满足条件时输出.紫书上说需要先判断1到k是否联通,不然会超时.交了一发直接深搜,果然TLE.所以需要先判连通. 判连通的方法有(能想到的): 1.dfs和bfs,两者感觉差不多,但是我选择的bfs 2.floyd,n^3的复杂度,但更加粗暴直接,也更好写 3.待添加 感悟: 不预先判连通3000ms超时