UVA 208 - Firetruck DFS 并查集剪枝

本文介绍了一种针对21个节点的深度优先搜索(DFS)路径查找算法,重点讨论了如何通过剪枝等优化手段避免超时,并采用并查集来辅助找到可达目标节点的有效路径。
21个节点   DFS搜索路径

每个点只可以访问一次 而且每条边只能访问一次  递归时改变状态  回溯时状态改回来

可能是图比较稀疏的原因   矩阵式的DFS  不加任何优化会超时  在我看来只有剪枝才可以过     边表的DFS不知道能不能过

看了下别人的思路  并查集找到能到fire的点  然后再进行回溯这样就能过了   至于大神们说的 tarjan  和  弗洛伊德算法 有兴趣的自己看吧


#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 25;

int root[maxn],vis[maxn][maxn],G[maxn][maxn],point[maxn],t[maxn],fa[maxn];
int T,sum,MAX;

int findset(int x)
{
    return fa[x] == x ? x: fa[x] = findset(fa[x]);
}

void Union(int x,int y)
{
    int fx,fy;
    fx = findset(x);
    fy = findset(y);
    if(fx != fy)
        fa[fx] = fy;
}

void DFS(int x,int cnt)
{
    if(x == T)
    {
        sum++;
        for(int i = 0; i < cnt - 1; i++)
            printf("%d ",root[i]);
        printf("%d\n",root[cnt-1]);
    }
    for(int i = 0; i < MAX; i++)
    {
        if(G[x][t[i]] == 1)
        {
            if(vis[x][t[i]] == 0 && point[t[i]] == 0)
            {
                vis[x][t[i]] = vis[t[i]][x] = point[t[i]] = 1;
                root[cnt] = t[i];
                DFS(t[i],cnt+1);
                vis[x][t[i]] = vis[t[i]][x] = point[t[i]] = 0;
            }
        }
    }
}

int main()
{
    #ifdef LOCAL
    freopen("in.txt","r",stdin);
    #endif // LOCAL
    int Case = 0;
    while(scanf("%d",&T) != EOF)
    {
        printf("CASE %d:\n",++Case);
        int x,y;
        memset(G,0,sizeof(G));
        memset(vis,0,sizeof(vis));
        memset(point,0,sizeof(point));
        for(int i = 0; i < maxn; i++)fa[i] = i;
        MAX = 0,sum = 0;
        root[0] = point[1] = 1;///标记point为1很重要  为了不产生重复的答案 /// 这里还有一个问题  如果起点只要有一个不是1  那么我的这个代码就是错的  但是只要稍微修改下就是一般化的代码了
        while(scanf("%d%d",&x,&y)&& x && y) 
        {
            Union(x,y);
            G[x][y] = G[y][x] = 1;

        }
        for(int i = 0; i < maxn; i++)
            if(findset(i) == findset(T))
                t[MAX++] = i;
        sort(t,t+MAX);
        DFS(1,1);
        printf("There are %d routes from the firestation to streetcorner %d.\n",sum,T);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值