zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    Android视图动画集合AndoridViewAnimations
    调整窗口大小时进行页面刷新(设定定时器)
    通过拖动来变换元素顺序
    jquery的input:type=file实现文件上传
    ajax请求的data数据格式
    Cookie的新增,设置与清除
    比较两个对象是否一样的代码
    5.3日,7:20开始 阮一峰js的早课学习
    在线代码编辑器使用案例代码
    layui当点击增加的时候,将form中的值获取的添加到table行中代码
  • 原文地址:https://www.cnblogs.com/sykline/p/10325726.html
Copyright © 2011-2022 走看看