HDU 6311 Euler road minimum edge coverage

Keywords: PHP

Original title: http://acm.hdu.edu.cn/showproblem.php?pid=6311

For a graph (not necessarily connected), at least how many strokes (paths) are needed to cover all edges and output paths.

Euler Road, for a connected graph, needs max (1, odd points / 2) pen to finish.

In this problem, for each connecting block, press "pair" to add edges to the points with odd degrees (only two points are left as the starting point and the ending point, which should be understood in this way). The added edge is the "virtual" edge.

After completing the diagram, run a dfs and add the edge to the set to find the path of Euler road.

During statistics, when encountering real edge, res + +, the path is added to the answer continuously. Until the virtual edge is encountered (it should be understood that it can't be finished in this stroke, so we need to start another stroke).

#include <bits/stdc++.h>

using namespace std;


int n,m;

int e = 0;


struct Edge{
    int u;
    int v;
    int id;
    bool vis;
    int next;
};

Edge edge[400005];
int head[100005];
int du[100005];

void addedge(int u,int v,int id) {

    edge[e].u = u;
    edge[e].v = v;
    edge[e].id = id;
    edge[e].vis = false;
    edge[e].next = head[u];
    head[u] = e++;
}


bool vis[100005];

vector<int> ji;

void dfs1(int u) {

    vis[u] = true;
    if(du[u] & 1) ji.push_back(u);
    for(int i = head[u]; i != -1; i = edge[i].next) {
        int to = edge[i].v;
        if(vis[to]) continue;
        dfs1(to);
    }
}

vector<int> ac;

void dfs2(int u) {

    for(int i = head[u]; i != -1; i = edge[i].next) {
        if(edge[i].vis) continue;
        edge[i].vis = true;
        edge[i ^ 1].vis = true;
        dfs2(edge[i].v);

        ac.push_back(edge[i].id);
    }
}

vector<int> ans[100005];
int res;
int main() {

    while(scanf("%d%d",&n,&m) != EOF) {

        e = 0;
        for(int i = 0; i <= n; i++) {
            head[i] = -1;
            vis[i] = false;
            du[i] = 0;
            ans[i].clear();
        }

        res = 0;




        int u,v;
        int id = 1;
        for(int i = 1; i <= m; i++) {
            scanf("%d%d",&u,&v);
            addedge(u,v,id);
            addedge(v,u,-id);
            id++;
            du[u]++;
            du[v]++;
        }


        for(int i = 1; i <= n; i++) {

            // Orphans and points that have been visited skip
            if(vis[i] || du[i] == 0) continue;

            // Find a connection block in dfs1, and find the point with odd degree
            ji.clear();
            dfs1(i);

            // For a connected block, if there is no point with odd degree
            // Then you can run Euler road from any point, otherwise you should start from the point with odd degree

            int st = ji.empty() ? i : ji[0];

            // Leave a pair of points, which should be the starting point and the ending point
            // If the degree of a connected graph is odd, it should be even
            for(int j = 2; j < ji.size(); j += 2) {
                addedge(ji[j],ji[j + 1],0);
                addedge(ji[j + 1],ji[j],0);
            }


            // dfs2, the Euler path of a complemented graph
            ac.clear();
            dfs2(st);


            for(int j = ac.size() - 1; j >= 0; j--) {
                // Virtual edge skip
                if(ac[j] == 0) continue;
                // Real edge, res++
                res++;

                // If it's all real, you can draw with one stroke
                while(ac[j] != 0 && j >= 0) {
                    ans[res].push_back(ac[j]);
                    j--;
                }

            }




        }

        // output
        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;
}

Posted by superpimp on Sun, 26 Jan 2020 09:17:52 -0800