HDU 6311 Cover (HDU多校第二次场) 欧拉路径

/**
 * 题目:给出一张无向图 求无向图的最小路径覆盖。换句话说就是一张图最少需要几笔画出来。
 * 那么很容易想到的是欧拉路径 -> 欧拉路径可以一笔画完 -> 欧拉路径是奇数度点个数为0 或则 为2的路径。
 * 扩展一下可以想到的是 对于无向图中的一个联通块来说 需要的最小路径数(欧拉路径数)为 max(d/2,1) d为图中奇数度点的个数。
 * 那么 接下来就是对该无向图中的每一个联通块跑一遍求欧拉路径的算法。
 * 对于每一个联通块来说。因为其是无向图,所以满足性质无向图中奇数度点的个数为偶数。
 * 于是只需要将奇数度点两两配对添边。那么该联通块就是一张欧拉图,我们用其跑求欧拉路径的算法,最后将增加的边删去,就得到了所有的欧拉路径。
 **/
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
struct Edge{
    int from,to,id;
    bool flag;
};
vector<Edge> edges;
vector<int> ways[maxn];
int degree[maxn],visn[maxn],n,m,res;
vector<int> expect,path,ans[maxn];
inline void init() {
    edges.clear();
    expect.clear();
    path.clear();
    memset(visn,0,sizeof(visn));
    for(int i=0;i<maxn;i++) {
        ways[i].clear();
        ans[i].clear();
        degree[i] = 0;
    }
    res = 0;
}
inline void addedge(int u,int v,int id) {
    edges.push_back((Edge){u,v,id,0});
    edges.push_back((Edge){v,u,-id,0});
    int sz = edges.size();
    ways[u].push_back(sz-2);
    ways[v].push_back(sz-1);
    degree[u]++;
    degree[v]++;
}
void dfs1(int rt) {
    visn[rt] = 1;
    if(degree[rt] & 1) expect.push_back(rt);
    for(int i=0;i<ways[rt].size();i++) {
        int to = edges[ways[rt][i]].to;
        if(!visn[to]) dfs1(to); 
    }
}
void dfs2(int rt) {
    for(int i=0;i<ways[rt].size();i++) {
        int e = ways[rt][i];
        if(edges[e].flag) continue;
        edges[e].flag = edges[e^1].flag = true;
        dfs2(edges[e].to);
        path.push_back(edges[e].id);
    }
}
int main()
{
    int u,v;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i=1;i<=m;i++) {
            scanf("%d%d",&u,&v);
            addedge(u,v,i);
        }
        for(int i=1;i<=n;i++) {
            if(visn[i] || degree[i] == 0) continue;
            expect.clear();
            dfs1(i);
            for(int j=2;j<expect.size();j+=2) {
                addedge(expect[j],expect[j+1],0);
            }
            path.clear();
            int rt = (expect.size()==0 ? i :expect[0]);
            dfs2(rt);
            for (int j = path.size() - 1; j >= 0; j--) {
                if (path[j] == 0) continue;
                res++;
                while (path[j] != 0 && j >= 0) {
                    ans[res].push_back(path[j]);
                    j--;
                }
                j++;//没用
            }
        }
        printf("%d\n", res);
        for (int i = 1; i <= res; i++) {
            printf("%d", ans[i].size());
            for (int j = 0; j < ans[i].size(); j++) {
                printf(" %d", ans[i][j]);
            }
            printf("\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_38013346/article/details/81279931