zoukankan      html  css  js  c++  java
  • HDU6311 Cover【欧拉路径 | 回路】

    HDU6311 Cover

    题意:

    给出(N)个点的简单无向图,不一定联通,现在要用最少的路径去覆盖所有边,并且每条边只被覆盖一次,问最少路径覆盖数和各条路径
    (Nle 10^5)

    题解:

    对于每个连通块分别处理
    考虑每个联通块,必然是用最少的欧拉路径去覆盖,首先考虑连通块里没有奇数度数的点的情况,这个情况下只要跑欧拉回路即可
    如果连通块中有(x)个奇数度数的点,那么显然(2|x),且必然是用(frac{x}{2})欧拉路径去覆盖,每两个奇数度数的顶点之间会有一条欧拉路径,考虑如何构造路径,首先将奇数度数的顶点两两配对连边,只剩下一对奇数度数点不连边,然后在新建的图中跑欧拉路径(此时必然存在欧拉路径),可以发现其中(frac{x}{2}-1)条新加入的边正好把路径分成了(frac{x}{2})条,这些分开来的路径正好是所求路径

    view code
    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    int n, m, deg[MAXN], bel[MAXN], vis[MAXN<<2], num[MAXN];
    vector<int> pt[MAXN];
    struct Graph{
        int head[MAXN],to[MAXN<<2],nxt[MAXN<<2],tot,id[MAXN<<2];
        void clear(){ tot = 0; memset(head,255,MAXN<<2); }
        void addEdge(int u, int v, int idd){
            to[tot] = v; nxt[tot] = head[u]; id[tot] = idd;
            vis[tot] = false; head[u] = tot++;
            to[tot] = u; nxt[tot] = head[v]; id[tot] = -idd;
            vis[tot] = false; head[v] = tot++;
        }
    }G;
    void mark(int u, int id){
        bel[u] = id;
        pt[id].push_back(u);
        for(int i = G.head[u]; ~i; i = G.nxt[i]){
            int v = G.to[i];
            if(!bel[v]) mark(v,id);
        }
    }
    stack<int> stk;
    void euler(int u){
        int now = ++num[u];
        for(int i = G.head[u]; ~i; i = G.nxt[i]){
            if(vis[i]) continue;
            G.head[u] = G.nxt[i];
            vis[i] = vis[i^1] = true;
            euler(G.to[i]);
            stk.push(G.id[i]);
            if(now!=num[u]) break;
        }
    }
    void print(){
        printf("%d ",stk.size());
        while(!stk.empty()){
            printf("%d%c",stk.top()," 
    "[stk.size()==1]);
            stk.pop();
        }
    }
    void rua(int id){
        int odddeg = 0;
        for(int &x : pt[id]) if(deg[x]&1) odddeg++;
        if(!odddeg){
            euler(pt[id][0]);
            print();
        }
        else{
            int last = -1;
            for(int &x : pt[id]){
                if(odddeg==2) break;
                if(deg[x]&1){
                    if(last==-1) last = x;
                    else{
                        G.addEdge(last,x,0);
                        deg[last]++; deg[x]++;
                        last = -1;
                        odddeg -= 2;
                    }
                }
            }
            for(int &x : pt[id]) if(deg[x]&1) last = x;
            euler(last);
            vector<int> vec;
            while(true){
                vec.clear();
                while(!stk.empty() and stk.top()!=0){
                    vec.push_back(stk.top());
                    stk.pop();
                }
                if(!stk.empty()) stk.pop();
                printf("%d",vec.size());
                for(int x : vec) printf(" %d",x);
                puts("");
                if(stk.empty()) break;
            }
        }
    }
    void solve(){
        G.clear();
        memset(deg+1,0,n<<2);
        for(int i = 1; i <= m; i++){
            int u, v; scanf("%d %d",&u,&v);
            G.addEdge(u,v,i);
            deg[u]++, deg[v]++;
        }
        int ID = 0;
        memset(bel+1,0,n<<2);
        int __count = 0;
        for(int i = 1; i <= n; i++) if(!bel[i]){
            pt[++ID].clear();
            mark(i,ID);
            if(pt[ID].size() > 1){
                int odddeg = 0;
                for(int x : pt[ID]) if(deg[x]&1) odddeg++;
                if(!odddeg) __count++;
                else __count += odddeg / 2;
            }
        }
        printf("%d
    ",__count);
        for(int i = 1; i <= ID; i++){
            if(pt[i].size() == 1) continue;
            rua(i);
        }
    }
    int main(){
        while(scanf("%d %d",&n,&m)!=EOF) solve();
        return 0;
    }
    
  • 相关阅读:
    村上春树的《海边的卡夫卡》与中日现实
    熊的甜蜜世界
    VS创建dll和调用dll
    DIRECTSHOW在VS2005中PVOID64问题和配置问题
    Vs 2008 解决方案的目录结构设置和管理
    SQL Server 2008中的代码安全(二):DDL触发器与登录触发器
    如何在自动SGA管理模式下调节参数设置
    将ORACLE数据库从归档改成非归档状态
    查看oracle数据库是否归档和修改归档模式(转)
    oracle TRANSLATE函数详解
  • 原文地址:https://www.cnblogs.com/kikokiko/p/13189907.html
Copyright © 2011-2022 走看看