UVA 208 - Firetruck DFS 并查集剪枝

来源:互联网 发布:数据库存储多个坐标 编辑:程序博客网 时间:2024/04/30 17:52
21个节点   DFS搜索路径

每个点只可以访问一次 而且每条边只能访问一次  递归时改变状态  回溯时状态改回来

可能是图比较稀疏的原因   矩阵式的DFS  不加任何优化会超时  在我看来只有剪枝才可以过     边表的DFS不知道能不能过

看了下别人的思路  并查集找到能到fire的点  然后再进行回溯这样就能过了   至于大神们说的 tarjan  和  弗洛伊德算法 有兴趣的自己看吧


#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 25;int root[maxn],vis[maxn][maxn],G[maxn][maxn],point[maxn],t[maxn],fa[maxn];int T,sum,MAX;int findset(int x){    return fa[x] == x ? x: fa[x] = findset(fa[x]);}void Union(int x,int y){    int fx,fy;    fx = findset(x);    fy = findset(y);    if(fx != fy)        fa[fx] = fy;}void DFS(int x,int cnt){    if(x == T)    {        sum++;        for(int i = 0; i < cnt - 1; i++)            printf("%d ",root[i]);        printf("%d\n",root[cnt-1]);    }    for(int i = 0; i < MAX; i++)    {        if(G[x][t[i]] == 1)        {            if(vis[x][t[i]] == 0 && point[t[i]] == 0)            {                vis[x][t[i]] = vis[t[i]][x] = point[t[i]] = 1;                root[cnt] = t[i];                DFS(t[i],cnt+1);                vis[x][t[i]] = vis[t[i]][x] = point[t[i]] = 0;            }        }    }}int main(){    #ifdef LOCAL    freopen("in.txt","r",stdin);    #endif // LOCAL    int Case = 0;    while(scanf("%d",&T) != EOF)    {        printf("CASE %d:\n",++Case);        int x,y;        memset(G,0,sizeof(G));        memset(vis,0,sizeof(vis));        memset(point,0,sizeof(point));        for(int i = 0; i < maxn; i++)fa[i] = i;        MAX = 0,sum = 0;        root[0] = point[1] = 1;///标记point为1很重要  为了不产生重复的答案 /// 这里还有一个问题  如果起点只要有一个不是1  那么我的这个代码就是错的  但是只要稍微修改下就是一般化的代码了        while(scanf("%d%d",&x,&y)&& x && y)         {            Union(x,y);            G[x][y] = G[y][x] = 1;        }        for(int i = 0; i < maxn; i++)            if(findset(i) == findset(T))                t[MAX++] = i;        sort(t,t+MAX);        DFS(1,1);        printf("There are %d routes from the firestation to streetcorner %d.\n",sum,T);    }    return 0;}


0 0
原创粉丝点击