(UVA - 208)Firetruck(路徑輸出問題,回溯+並查集/floyd演算法+dfs)

feng_zhiyu發表於2017-08-13

題目連結: 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;
}

相關文章