(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;}