Cover

PS:最少路径覆盖。统计当前连通块中度数为奇数的顶点,然后留两个顶点作为DFS的起点和终点,其它的顶点每两个连一条虚边,使得度数为偶数个。据说有孤立的点;链式前向星的tot从1开始,并且第一条边的编号从2开始,,,,为了好计算边的序号(1 ~ m)。总之还是有编程技巧的。

#include "stdafx.h"
#pragma warning(disable:4996)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#define ll long long
#define P pair<int, int>
#define PP pair<int,pair<int, int>>
#define pb push_back
#define pp pop_back
#define lson root << 1
#define INF (int)2e9 + 7
#define rson root << 1 | 1
#define LINF (unsigned long long int)1e18
#define mem(arry, in) memset(arry, in, sizeof(arry))
using namespace std;

const int N = 100005;

int n, m, tot, cnt;
int head[4 * N], vis[4 * N], use[4 * N], deg[N];

vector<int> v, ans[N];

struct node { int to, next;  } e[4 * N];

void Inite() {
    cnt = 0;
    tot = 1;
    mem(head, 0), mem(vis, 0), mem(use, 0), mem(deg, 0);
}

void addedge(int u, int v) {
    e[++tot].to = v;
    e[tot].next = head[u];
    head[u] = tot;
}

void DFS(int u) {
    vis[u] = 1;
    if (deg[u] & 1) v.pb(u);
    for (int i = head[u]; i != 0; i = e[i].next) {
        int v = e[i].to;
        if (!vis[v]) DFS(v);
    }
}
// 搜索路径
void Find(int u) {
    for (int i = head[u]; i != 0; i = e[i].next) {
        int v = e[i].to;
        if (!use[i]) {
            use[i] = use[i ^ 1] = 1;
            Find(v);
            if (i > 2 * m + 1) cnt++;        // 虚边,说明这是一条路径的起点
            else {
                int tp = ((i & 1) == 1 ? i / 2 : -i / 2);     
                ans[cnt].pb(tp);
            }
        }
    }
}

void Solve() {
    for (int i = 1; i <= n; i++) {
        if (!vis[i] && deg[i]) {
            DFS(i);
            int r = (int)v.size();
            for (int j = 2; j < r; j += 2) {
                addedge(v[j], v[j + 1]);
                addedge(v[j + 1], v[j]);
            }
            cnt++;
            if (r) Find(v[0]);
            else Find(i);
            v.clear();
        }
    }
    
    printf("%d\n", cnt);
    for (int i = 1; i <= cnt; i++) {
        int r = (int)ans[i].size();
        printf("%d ", r);
        for (int j = 0; j < r; j++) {
            printf("%d%c", ans[i][j], (j + 1 == r ? '\n' : ' '));
        }
        ans[i].clear();
    }
}


int main()
{
    while (scanf("%d %d", &n, &m) != EOF) {
        Inite();
        for (int i = 1; i <= m; i++) {
            int u, v;
            scanf("%d %d", &u, &v);
            addedge(u, v);
            addedge(v, u);
            deg[u]++;
            deg[v]++;
        }
        Solve();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zgglj-com/p/9392281.html