• hdu 3018 欧拉路定理+并查集


    题目:hdu 3018
    题意:
    有一些道路,每次只能走一遍,问最少几次走遍所有道路?
    分析:
    这题是经典问题:一笔画问题。解决这个问题,需要知道几个定理和定义:
    1. 欧拉道路:能否从无向图中的一个节点出发走出一条道路,每条边恰好经过一次,这样的路线称为欧拉道路。
    2. 如果一个图是联通的且最多只有两个奇度点,则一定存在欧拉道路。如果有两个奇度点,则必须从其中一个出发,回到另一个终止。如果没有奇度点,可以从任一点出发。
    3. 对于有向图,如果想构成欧拉路,那么:最多只能有两个点的入读不等于出度,而且必须是其中一个点的出度比入度大一,另一个点的入度比出度大一。

    对于这题:先用并查集找出连通图,然后再找出每个连通块中奇度点的个数,如果没有奇度点,那么只需要一笔,如果有奇度点,那么需要奇点的个数/2笔。另外,这题独立点需要忽略掉。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int N=100000+5;
    int fa[N];
    int findfa(int x){return x==fa[x]?x:fa[x]=findfa(fa[x]);}
    int de[N],cnt[N],vis[N];
    int main()
    {
        int n,m;
        while(~scanf("%d%d",&n,&m)){
            for(int i=1;i<=n;i++)fa[i]=i;
            memset(de,0,sizeof(de));
            memset(vis,0,sizeof(vis));
            memset(cnt,0,sizeof(cnt));
            int u,v;
            for(int i=0;i<m;i++){
                scanf("%d%d",&u,&v);
                de[u]++;de[v]++;
                int x=findfa(u),y=findfa(v);
                if(x!=y)fa[x]=y;
            }
            vector<int>ans;
            for(int i=1;i<=n;i++){
                int x=findfa(i);
                if(!vis[x]){
                    vis[x]=1;
                    ans.push_back(x);
                }
                if(de[i]&1){
                    cnt[x]++;
                }
            }
            int sum=0;
            for(int i=0;i<ans.size();i++){
                int x=ans[i];
                if(de[x]==0)continue; //独立点忽略掉
                if(cnt[x]==0)sum++;
                else sum+=cnt[x]/2;
            }
            printf("%d
    ",sum);
        }
        return 0;
    }
    
  • 相关阅读:
    django错误参考
    Pyhton模块学习
    jmeter
    SQL SERVER 2008
    touch的属性
    Sql Server Alter语句
    安装LoadRunner提示缺少vc2005_sp1_with_atl..
    sql语句
    数据库的知识
    十天学会<div+css>横向导航菜单和纵向导航菜单
  • 原文地址:https://www.cnblogs.com/01world/p/5651250.html
Copyright © 2020-2023  润新知