zoukankan      html  css  js  c++  java
  • 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
    ", 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 ? '
    ' : ' '));
            }
            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;
    }
  • 相关阅读:
    基于.NET CORE微服务框架 -谈谈Cache中间件和缓存降级
    基于.NET CORE微服务框架 -谈谈surging的服务容错降级
    基于.NET CORE微服务框架 -surging的介绍和简单示例 (开源)
    Git学习记录-基本命令篇
    一个实例搞懂二重指针
    不能将X*类型的值分配到X*类型的实体问题的解决方法
    如何将idea工程打包成jar文件
    windows10环境下安装深度学习环境anaconda+pytorch+CUDA+cuDDN
    指针、地址和引用学习笔记
    几行代码实现cookie的盗取
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9392281.html
Copyright © 2011-2022 走看看