UVa 10596 - Morning Walk, 赤裸裸的欧拉回路

本文深入分析了一个名为Kamal的个体在从Dinajpur搬迁到Chittagong后,如何通过每天早晨的不同路径漫步来避免重复路线,并探究了他是否有可能在一次行走中覆盖所有道路。通过使用欧拉回路的概念,文章提供了解决该问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FILE10596-Morning Walk3791
37.43%
1073
89.84%

题目链接:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=105&page=show_problem&problem=1537


题目:

Kamalis aMotashotaguy. He has got a new job inChittagong. So, he has moved toChittagongfromDinajpur. He was getting fatter inDinajpuras he had no work in his hand there. So, moving toChittagonghas turned to be a blessing for him. Every morning he takes a walk through the hilly roads of charming cityChittagong. He is enjoying this city very much. There are so many roads inChittagongand every morning he takes different paths for his walking. But while choosing a path he makes sure he does not visit a road twice not even in his way back home. An intersection point of a road is not considered as the part of the road. In a sunny morning, he was thinking about how it would be if he could visit all the roads of the city in a single walk. Your task is to helpKamalin determining whether it is possible for him or not.


题目大意:

Kamal每天早上都要从家里走到Chittagongand这个地方。 从家里到Chittagongand有很多条路, 他每天早上都要先选择好一条路线, 这条路线从家里走到Chittagongand,在从Chittagongand走回家里。 这条路线不能重复地经过同一条路。 两个地点间可能会有多条路。 比如多次出现了从A到B的路线, 那么表示每次出现的都是不同的路


分析与总结:

这题就是赤裸裸的欧拉回路。UVa 10054 - The Necklace UVa 10129 - Play on Words 这两篇讲得较详细。 不再累赘


1. 欧拉回路+DFS

#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
int vis[210],N, M, G[210][210], inDegree[210], outDegree[210];

void dfs(int v)         //深度优先遍历  
{  
    vis[v]=true;  
    for(int i=0;i<N;i++)  
    {  
        if(!vis[i] && G[v][i])  
        {  
            dfs(i);  
        }  
    }  
}  

int main(){
#ifdef LOCAL
    freopen("input.txt","r",stdin);
#endif
    while(~scanf("%d %d",&N, &M)){
        memset(G, 0, sizeof(G));
        int a,b;
        memset(vis, 0, sizeof(vis));
        for(int i=0; i<M; ++i){
            scanf("%d %d",&a,&b);
            G[a][b] = G[b][a] = 1;
            ++vis[a]; 
            ++vis[b];
        }
        
        int cnt = 0;
        for(int i=0; i<N; ++i){
            if(vis[i]%2==1){
                ++cnt;
                break;
            }
        }
        memset(vis, 0, sizeof(vis));
        if(cnt || M<2) printf("Not Possible\n");
        else{
            dfs(0);
            bool flag = true;
            for(int i=0; i<N; ++i) {
                if(!vis[i]) flag = false;
            }
            if(flag)printf("Possible\n");
            else printf("Not Possible\n");
        }
    
    }
    return 0;
}

2,欧拉回路+并查集

#include<cstring>
#include<iostream>
#include<cstdio>
using namespace std;
int vis[210],N, M, G[210][210], inDegree[210], outDegree[210], f[210];

void init()   //并查集判断是否是一个连通图  
{  
    int i;  
    for(i=0;i<N;i++)  
        f[i]=i;  
}  
int find(int x)  
{  
    int r=x;  
    while(f[r]!=r)  
    r=f[r];  
    f[x]=r;  
    return r;  
}  
void Union(int x,int y)  
{  
    int fx,fy;  
    fx=find(x);  
    fy=find(y);  
    if(fx!=fy)  
    f[fx]=fy;  
}  

int main(){
#ifdef LOCAL
    freopen("input.txt","r",stdin);
#endif
    while(~scanf("%d %d",&N, &M) && N){
        memset(G, 0, sizeof(G));
        int a,b;
        init();
        memset(vis, 0, sizeof(vis));
        for(int i=0; i<M; ++i){
            scanf("%d %d",&a,&b);
            ++G[a][b];
            ++G[b][a];
            ++vis[a];
            ++vis[b];
            Union(a,b);
        }
        
        int ans=0;
        for(int i=0; i<N; ++i) if(f[i]==i) ++ans;
        
        if(ans==1 && M>=2){
            int cnt = 0;
            for(int i=0; i<N; ++i){
                if(vis[i]%2==1){
                    ++cnt;
                    break;
                }
            }
            if(cnt) printf("Not Possible\n");
            else printf("Possible\n");
        }
        else
            printf("Not Possible\n"); 
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值