zoukankan      html  css  js  c++  java
  • HDU

    题意

    给个无向图,无重边和自环,问最少需要多少路径把边覆盖了。并输出相应路径

    分析

    首先联通块之间是独立的,对于一个联通块内,最少路径覆盖就是  max(1,度数为奇数点的个数/2)。然后就是求欧拉路径了,先将块内度数为奇数的点找出来,留下两个点,其余两两连上虚边,这样我们选择从一个奇数点出发到另一个奇数点,求出一条欧拉路径,统计总路径数。接着就dfs,注意一些细节。

    附赠一个求欧拉回路的fleury算法:https://blog.csdn.net/u011466175/article/details/18861415

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <cmath>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <stack>
    #include <set>
    #include <bitset>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    #define ms(a, b) memset(a, b, sizeof(a))
    #define pb push_back
    #define mp make_pair
    #define pii pair<int, int>
    #define eps 0.0000000001
    #define IOS ios::sync_with_stdio(0);cin.tie(0);
    #define random(a, b) rand()*rand()%(b-a+1)+a
    #define pi acos(-1)
    const ll INF = 0x3f3f3f3f3f3f3f3fll;
    const int inf = 0x3f3f3f3f;
    const int maxn = 100000 + 10;
    const int maxm = 200000 + 10;
    const int mod = 1e9+7;
    
    struct ND{
        int v,nxt;
        ND(){}
        ND(int _v,int _nxt):v(_v),nxt(_nxt){}
    }e[maxn*10];
    bool pvis[maxn],evis[maxn*10];
    int head[maxn],du[maxn],tot;
    int n,m,cnt;
    vector<int> ans[maxn],odd;
    void init(){
        cnt=tot=0;
        memset(head,-1,sizeof(head));
        memset(du,0,sizeof(du));
        memset(pvis,false,sizeof(pvis));
        memset(evis,false,sizeof(evis));
        for(int i=0;i<=n;i++) ans[i].clear();
    }
    void addedge(int u,int v){
        e[tot]=ND(v,head[u]);head[u]=tot++;
        e[tot]=ND(u,head[v]);head[v]=tot++;
    }
    void dfs1(int u){
        pvis[u]=true;
        if(du[u]%2) odd.push_back(u);//同一联通块里奇数度的点
        for(int i=head[u];~i;i=e[i].nxt){
            int v = e[i].v;
            if(!pvis[v]){
                dfs1(v);
            }
        }
    }
    void dfs2(int u){
        for(int i=head[u];~i;i=e[i].nxt){
            int v=e[i].v;
            if(!evis[i]){
                evis[i]=evis[i^1]=true;//判断边有没有走过
                dfs2(v);
                int tmp=i%2?-(i+1)/2:i/2+1; //对应边的编号
                if(i<2*m) ans[cnt].push_back(tmp); //为原先存在的边
                else cnt++; //新连的虚边
            }
        }
    }
    int main(){
    #ifdef LOCAL
        freopen("in.txt", "r", stdin);
    //    freopen("output.txt", "w", stdout);
    #endif
        while(~scanf("%d%d",&n,&m)){
            init();
            int u,v;
            for(int i=0;i<m;i++){
                scanf("%d%d",&u,&v);
                addedge(u,v);
                du[u]++,du[v]++;
            }
            for(int i=1;i<=n;i++){
                if(!pvis[i]&&du[i]){
                    odd.clear();
                    dfs1(i);
                    for(int i=2;i<odd.size();i+=2){//保留两个奇度点,其余两两连边
                        addedge(odd[i],odd[i+1]);
                    }
                    int rt = odd.size()?odd[0]:i;
                    dfs2(rt);
                    cnt++;
                }
            }
            printf("%d
    ",cnt);
            for(int i=0;i<cnt;i++){
                printf("%d",ans[i].size());
                for(int j=ans[i].size()-1;j>=0;j--){
                    printf(" %d",ans[i][j]);
                }puts("");
            }
        }
    
        return 0;
    }
  • 相关阅读:
    时装画基础知识--如何画人体
    马士兵java视频学习顺序
    Mysql 中文字符乱码问题
    zendstudio 设置默认编码 utf-8 gbk
    MYSQL 本地无ROOT权限 忘记密码
    windows 3389 远程
    windows 老掉牙CMD的命令
    mysql-常用注入渗透手法
    ubuntu 添加多个IP
    windows下简单配置apache
  • 原文地址:https://www.cnblogs.com/fht-litost/p/9551643.html
Copyright © 2011-2022 走看看