UVa208 消防车 (dfs+并查集)

来源:互联网 发布:苏亚星网络备课系统 编辑:程序博客网 时间:2024/04/30 08:27

UVa208 Firetruck
题意:一个n(n<=20)个结点的无向图,要求打印从结点1到结点k的所有路径。
解法:简单的dfs,但是会超时,因为有些结点不能到达k,所以搜索这些结点完全是多余的,可以用并查集将能到达k的结点放入一个集合,搜索这些结点就可以了。

#include<cstdio>#include<cstring>#include<iostream>using namespace std;int k;int g[20+5][20+5];//邻接矩阵int vis[20+5];int path[20+5];//记录路径,方便打印int cnt;int p[20+5];int Find(int x){    if(p[x]==x)return x;    return p[x]=Find(p[x]);}bool read(){    if(scanf("%d",&k)==EOF)return 0;    for(int i=1;i<=20;i++)p[i]=i;    memset(g,0,sizeof(g));    memset(vis,0,sizeof(vis));    int x,y;    while(scanf("%d%d",&x,&y),x||y){        g[x][y]=g[y][x]=1;        p[Find(x)]=Find(y);//可达点放入同一个集合    }    return 1;}void dfs(int cur,int dep){    if(cur==k){        cnt++;        for(int i=1;i<=dep;i++){            if(i!=1)printf(" ");            printf("%d",path[i]);        }        puts("");        return;    }    for(int i=1;i<=20;i++){        if(g[cur][i]&&vis[i]==0){            vis[i]=1;            path[dep+1]=i;            dfs(i,dep+1);            vis[i]=0;        }    }}int main(){    int t=1;    while(read()){        printf("CASE %d:\n",t++);        vis[1]=1;        for(int i=1;i<=20;i++){//不能到达起火点的节点在搜索前就要先排除,否则搜索会超时            if(Find(i)!=Find(k))vis[i]=1;//标记已访问即可        }        cnt=0;        path[1]=1;        dfs(1,1);        printf("There are %d routes from the firestation to streetcorner %d.\n",cnt,k);    }}
0 0