(UVA

来源:互联网 发布:下载word2010软件 编辑:程序博客网 时间:2024/06/15 14:49

题目链接: https://vjudge.net/problem/UVA-208

题意:输入一个n(n<=20)个节点的无向图以及某个节点k,按照字典序从小到大顺序输出从节点1到节点k的所有路径,要求节点不能重复。

分析:路径输出问题,路径的第一个和最后一个点是固定的,可以用dfs从小到大搜索,回溯求出所有的路径记录并输出。 注意要提前判断节点1是否可以到达节点k,不然会TLE。

提前判断能否到达,我写了两种:1.并查集 2.floyd算法
并查集当然是可以判断的,floyd算法可以用是因为数据n不是特别大

#include<cstdio>#include<set>#include<cstring>#include<sstream>#include<iostream>#include<algorithm>using namespace std;#define mem(a,n) memset(a,n,sizeof(a))typedef long long LL;const int N=25;const int INF=0x3f3f3f3f;int a[N][N],d[N][N];int n,vis[N],ans,b[N];int MAX,par[N];#define same(x,y) Find(x)==Find(y)void floyd()///floyd算法求最短路径,在此题中起判断作用{    for(int k=1;k<=MAX;k++)        for(int i=1;i<=MAX;i++)        for(int j=1;j<=MAX;j++)        d[i][j]=min(d[i][j],d[i][k]+d[k][j]);}void init(){    for(int i=0; i<N; i++)        par[i]=i;}int Find(int x){    return par[x]==x?x:Find(par[x]);}void unite(int x,int y){    x=Find(x);    y=Find(y);    if(x!=y)        par[x]=y;}void dfs(int cur,int pos)///搜索所有的可行路径{    if(cur==n)///可以到达点n    {        ans++;///可行方案数+1        printf("1");        for(int i=1; i<pos-1; i++)            printf(" %d",b[i]);        printf(" %d\n",n);        return ;    }    for(int i=1; i<=MAX; i++)///依次遍历    {        if(!vis[i]&&a[cur][i]==1&&same(i,n))///same()函数起判断作用,a[cur][i]==1代表必须有路径,vis判重        {            b[pos]=i;            vis[i]=1;            dfs(i,pos+1);            vis[i]=0;///回溯        }    }}int main(){    int cas=1;    while(~scanf("%d",&n))    {        init();        printf("CASE %d:\n",cas++);        MAX=0;////MAX记录无向图节点的最大编号值        mem(d,INF);        mem(a,0);        int x,y;        while(~scanf("%d%d",&x,&y)&&x&&y)        {            unite(x,y);            a[x][y]=a[y][x]=1;///=1表示联通            MAX=max(MAX,max(x,y));        }//       floyd();        vis[1]=1;        ans=0;        dfs(1,1);///从节点1开始搜索        printf("There are %d routes from the firestation to streetcorner %d.\n",ans,n);    }    return 0;}