zoukankan      html  css  js  c++  java
  • HDU6311 Cover (欧拉路径->无向图有最少用多少条边不重复的路径可以覆盖一个张无向图)

    题意:有最少用多少条边不重复的路径可以覆盖一个张无向图 ,输出每条路径的边的序号 , 如果是反向就输出-id。

    也就是可以多少次一笔画的方式画完这个无向图。

    题解:我们已知最优胜的情况是整个图是欧拉图的时候 ,我们只需要一笔就搞定了 , 可是现在这个图并不是一个欧拉图, 所以现在问题是其转化为欧拉图 ,那我们根据欧拉图的性质 , 如果一个无向图是欧拉图的时候当且这个图有奇数的度的点有0个或者是2个 , 而且如果是两个的话那这两个点肯定是起点或者终点  ;  所以现在我们就遍历整个图的奇数点将其连接成为一个欧拉图 , 然后跑一遍求欧拉路径的算法 ,如果遇到的是我们构造出的虚拟边 , 是不是就是意味着这里是一个断点 ,需要我们重新起笔在画;

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    using namespace std;
    typedef long long ll ;
    const int maxn = 1e5+5;
    struct Edge
    {
        int to,id,next;
        bool f;
    }edges[maxn<<4];
    int fa=0;
    int tot , head[maxn] , cnt;
    bool vis[maxn];
    vector<int> res[maxn];
    int deg[maxn];
    void init()
    {
        tot = 0;
        cnt = 0;
        memset(deg,0,sizeof(deg));
        memset(vis,0,sizeof(vis));
        memset(head,-1,sizeof(head));
    }
    void AddEdge(int u , int v , int id)
    {
        edges[tot].f=0; edges[tot].to = v ; edges[tot].id=id;
        edges[tot].next = head[u] ; head[u] = tot++;
    }
    
    void dfs(int u)
    {
        vis[u]=true;
        for(int i=head[u] ; ~i ; i=edges[i].next)
        {
            int v=edges[i].to , id =edges[i].id;
            if(!edges[i].f)
            {
                edges[i].f = edges[i^1].f=true; //将边和反向边标记
                dfs(v);
                if(id) res[cnt].push_back(-id); ///退丈记录边id
                else cnt++; ///扫到虚边,那么路径加1
            }
        }
    }
    void Print()
    {
        printf("%d
    ",cnt);
        for(int i=1 ; i<=cnt ; i++)
        {
            printf("%d",res[i].size());
            for(int j=0 ; j<res[i].size() ; ++j)
                printf(" %d",res[i][j]);
            puts("");
            res[i].clear();
        }
    }
    int main()
    {
        int T,N,M,u,v,tmp;
        while(~scanf("%d%d",&N,&M))
        {
            init();
            for(int i=1 ; i<=M ; i++)
            {
                scanf("%d%d",&u,&v);
                deg[u]++ , deg[v]++;
                AddEdge(u,v,i);
                AddEdge(v,u,-i);
            }
            ///将图的奇数的度连起
            u=0;
            for(int i=1 ; i<=N ; i++)
            {
                if(deg[i]&1)
                {
                    if(u)
                    {
                        AddEdge(u,i,0);
                        AddEdge(i,u,0);
                        u=0;
                    }
                    else u=i;
                }
            }
    
    
            for(int i=1 ; i<=N ; i++)
            {
                if(!vis[i] && (deg[i]&1))
                {
                    cnt++;   ///细节处理cnt , 如果出现虚边cnt++ , 下次dfs()还cnt++ , 这是不对的
                    dfs(i);
                    cnt--;
                }
            }
            for(int i=1 ; i<=N ; i++)
            {
                if(!vis[i] && deg[i])
                {   
                    cnt++;  ///偶数的点不会出现虚遍
                    dfs(i);
                  
                }
            }
            Print();
        }
        return 0;
    }
    View Code

    参考出

  • 相关阅读:
    通过队列实现进程间的通信(使用阻塞方式调用func函数)
    Scrapy 项目:QuotesBot
    数据分析_找数据参考网站
    Matplotlib 图表绘制工具学习笔记
    Python算法_斐波那契数列(10)
    Python算法_排序数组(09)
    Python数据结构与算法_反转字符串(08)
    Python算法_爬楼梯(08)
    Python数据结构与算法_搜索插入位置(07)
    Python数据结构与算法_删除排序数组中的重复项(06)
  • 原文地址:https://www.cnblogs.com/shuaihui520/p/10282411.html
Copyright © 2011-2022 走看看