• UVA


    题目:

    给出一个结点d和一个无向图中所有的边,按字典序输出这个无向图中所有从1到d的路径。

    思路:

    1.看到紫书上的提示,如果不预先判断结点1是否能直接到达结点d,上来就直接dfs搜索的话会超时,于是就想到了用并查集来预先判断是否属于同一个连通分量。

    2.可以将与d属于同一个连通分量的点用一个数组保存起来,然后dfs搜索这个数组就可以了,这也就是只搜索了与d在一个连通分量里的点。

    3.当搜索到d的时候就输出路径。

    代码:

    #include <bits/stdc++.h>
    #define inf 0x3f3f3f3f
    #define MAX 1e3
    #define FRE() freopen("in.txt","r",stdin)
    #define FRO() freopen("out.txt","w",stdout)
    using namespace std;
    typedef long long ll;
    const int maxn = 22;
    bool mp[maxn][maxn];
    int fa[maxn],d,lk[maxn],vis[maxn];
    int idx,path[maxn],cnt;
    
    void init(){
        for(int i=0; i<maxn; i++){
            fa[i] = i;
        }
        memset(lk,0,sizeof(lk));
        memset(vis,0,sizeof(vis));
        memset(mp,0,sizeof(mp));
        memset(path,0,sizeof(path));
    }
    
    int _find(int x){//并查集查找祖先
        return fa[x]==x ? x : fa[x] = _find(fa[x]);
    }
    
    void mergeNode(int x,int y){//合并不属于同一个连通分量的两个点
        int tx = _find(x),ty = _find(y);
        if(tx != ty){
            fa[tx] = ty;
        }
    }
    
    bool isLinked(int x,int y){//判断两个点是不是属于同一个连通分量
        if(_find(x)!=_find(y)){
            return false;
        }
        return true;
    }
    
    void DFS(int now, int MX){
        if(now==d){//搜索到d就输出;路径
            cnt++;
            printf("1");
            for(int i=0; i<MX; i++){
                printf(" %d",path[i]);
            }
            printf("
    ");
        }else{
            //cout<<now<<endl;
            for(int i=1; i<idx; i++){
                int u = lk[i];
                if(!vis[u] && mp[now][u]){
                    vis[u] = true;
                    path[MX] = u;//这里其实没必要另开一个数组保存路径,在下一个循环的时候当前的路径已经输出或没用了
                    DFS(u,MX+1);
                    vis[u] = false;
                }
            }
        }
    }
    
    void check(){
        for(int i=0; i<idx; i++){
            printf("%d ",lk[i]);
        }
        printf("
    ");
    }
    
    int main(){
        //FRE();
        int kase=0;
        while(scanf("%d",&d)!=EOF){
            int st,en;
            init();
            while(scanf("%d%d",&st,&en)&&st){
                mp[st][en] = 1;
                mp[en][st] = 1;
                mergeNode(st,en);
            }
            printf("CASE %d:
    ",++kase);
            if(isLinked(1,d)==false){
                printf("There are 0 routes from the firestation to streetcorner %d.
    ",d);
            }else{
                idx=0;
                for(int i=1; i<maxn; i++){//找到与d在同一个连通分量里边的点并保存
                    if(isLinked(i, d)){
                        lk[idx++] = i;
                    }
                }
                sort(lk,lk+idx);//从小到大排序,保证字典序
                //check();
                cnt = 0;
                DFS(1, 0);
                printf("There are %d routes from the firestation to streetcorner %d.
    ",cnt,d);
            }
        }
        return 0;
    }
  • 相关阅读:
    colemak,你用了吗?
    DELPHI一个对付内存汇漏的办法和技巧
    使用for in 循环数据集
    今天差点被断电搞死了,幸好IDE的备份救了我
    为什么继续选择DELPHI?
    无缘DELPHI的BUG
    DELPHI DOUBLE不解之迷
    失败的大牛事件委托,与我的委托
    2017-02-08 01:19:09 Scrapy: pk5_mylist
    2016-09-02 16:50:15 webqq 协议分析
  • 原文地址:https://www.cnblogs.com/sykline/p/10325726.html
Copyright © 2020-2023  润新知