您的位置:首页 > 其它

(UVA - 208)Firetruck(路径输出问题,回溯+并查集/floyd算法+dfs)

2017-08-13 09:44 483 查看
题目链接: 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

,d

;
int n,vis
,ans,b
;
int MAX,par
;

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  搜索 uva dfs floyd算法