HDU - 6311 Cover(无向图的最少路径边覆盖 欧拉路径)

题意

给个无向图,无重边和自环,问最少需要多少路径把边覆盖了。并输出相应路径

分析

首先联通块之间是独立的,对于一个联通块内,最少路径覆盖就是  max(1,度数为奇数点的个数/2)。然后就是求欧拉路径了,先将块内度数为奇数的点找出来,留下两个点,其余两两连上虚边,这样我们选择从一个奇数点出发到另一个奇数点,求出一条欧拉路径,统计总路径数。接着就dfs,注意一些细节。

附赠一个求欧拉回路的fleury算法:https://blog.csdn.net/u011466175/article/details/18861415

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(a, b) memset(a, b, sizeof(a))
#define pb push_back
#define mp make_pair
#define pii pair<int, int>
#define eps 0.0000000001
#define IOS ios::sync_with_stdio(0);cin.tie(0);
#define random(a, b) rand()*rand()%(b-a+1)+a
#define pi acos(-1)
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int inf = 0x3f3f3f3f;
const int maxn = 100000 + 10;
const int maxm = 200000 + 10;
const int mod = 1e9+7;

struct ND{
    int v,nxt;
    ND(){}
    ND(int _v,int _nxt):v(_v),nxt(_nxt){}
}e[maxn*10];
bool pvis[maxn],evis[maxn*10];
int head[maxn],du[maxn],tot;
int n,m,cnt;
vector<int> ans[maxn],odd;
void init(){
    cnt=tot=0;
    memset(head,-1,sizeof(head));
    memset(du,0,sizeof(du));
    memset(pvis,false,sizeof(pvis));
    memset(evis,false,sizeof(evis));
    for(int i=0;i<=n;i++) ans[i].clear();
}
void addedge(int u,int v){
    e[tot]=ND(v,head[u]);head[u]=tot++;
    e[tot]=ND(u,head[v]);head[v]=tot++;
}
void dfs1(int u){
    pvis[u]=true;
    if(du[u]%2) odd.push_back(u);//同一联通块里奇数度的点
    for(int i=head[u];~i;i=e[i].nxt){
        int v = e[i].v;
        if(!pvis[v]){
            dfs1(v);
        }
    }
}
void dfs2(int u){
    for(int i=head[u];~i;i=e[i].nxt){
        int v=e[i].v;
        if(!evis[i]){
            evis[i]=evis[i^1]=true;//判断边有没有走过
            dfs2(v);
            int tmp=i%2?-(i+1)/2:i/2+1; //对应边的编号
            if(i<2*m) ans[cnt].push_back(tmp); //为原先存在的边
            else cnt++; //新连的虚边
        }
    }
}
int main(){
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);
#endif
    while(~scanf("%d%d",&n,&m)){
        init();
        int u,v;
        for(int i=0;i<m;i++){
            scanf("%d%d",&u,&v);
            addedge(u,v);
            du[u]++,du[v]++;
        }
        for(int i=1;i<=n;i++){
            if(!pvis[i]&&du[i]){
                odd.clear();
                dfs1(i);
                for(int i=2;i<odd.size();i+=2){//保留两个奇度点,其余两两连边
                    addedge(odd[i],odd[i+1]);
                }
                int rt = odd.size()?odd[0]:i;
                dfs2(rt);
                cnt++;
            }
        }
        printf("%d\n",cnt);
        for(int i=0;i<cnt;i++){
            printf("%d",ans[i].size());
            for(int j=ans[i].size()-1;j>=0;j--){
                printf(" %d",ans[i][j]);
            }puts("");
        }
    }

    return 0;
}

原文地址:https://www.cnblogs.com/fht-litost/p/9551643.html

时间: 2024-10-12 19:29:07

HDU - 6311 Cover(无向图的最少路径边覆盖 欧拉路径)的相关文章

HDU 6311 Cover

Cover Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 440    Accepted Submission(s): 65Special Judge Problem Description The Wall has down and the King in the north has to send his soldiers to s

hdu 6311 Cover (欧拉路径)

#include<bits/stdc++.h> #define N 100005 using namespace std; struct Edge{ int to,next; bool able; }edge[N*4];///要多于总边数的4倍 (*2双向边 并且可能加边) int n,m, Degree[N],///每个点的度 Head[N], ///每个点的最后一条加入的边的序号 cnt, ///边的序号 res; ///一共找到的路径 bool vis[N]; vector<int

HDU 1151 Air Raid(最小路径覆盖 = 顶点数 - 最大匹配数)

Air Raid Problem Description Consider a town where all the streets are one-way and each street leads from one intersection to another. It is also known that starting from an intersection and walking through town's streets you can never reach the same

hdu 4862 KM算法 最小K路径覆盖的模型

http://acm.hdu.edu.cn/showproblem.php?pid=4862 选t<=k次,t条路要经过所有的点一次并且仅仅一次, 建图是问题: 我自己最初就把n*m 个点分别放入X集合以及Y集合,再求最优匹配,然后连样例都过不了,而且其实当时解释不了什么情况下不能得到结果,因为k此这个条件相当于没用上... 建图方法: 1.X集合和Y集合都放入n*m+k个点,X中前n*m个点和Y中前n*m个点之间,如果格子里的值相等,权就是(收益-耗费),不等就是(-耗费),因为要的是最大收益

poj1041 John&#39;s trip,无向图求欧拉回路路径

点击打开链接 无向图求欧拉回路: 1.图连通 2.所有顶点的度数位偶数 #include <cstdio> #include <cstring> #include <stack> #include <queue> #include <algorithm> using namespace std; const int mt = 2000; const int ms = 50; bool vis[mt+5]; int g[ms][mt+5]; int

HDU 4862 Jump(最小K路径覆盖)

输入一个n×m网格图,每个结点的值为0-9,可以从任意点出发不超过k次,走完每个点且仅访问每个结点一次,问最终的能量最大值.不可全部走完的情况输出-1. 初始能量为0. 而结点(x,y)可以跳跃到结点(x,y+dy)或(x+dx,y).消耗能量为跳跃前后结点的曼哈顿距离 - 1 .若跳跃前后的结点的值相等,能量加上那个值. 具体建图可以参考这里http://blog.sina.com.cn/s/blog_6bddecdc0102uy9g.html 最小K路径覆盖其实在之前是见过的打过的,不过这次

poj 1422 Air Raid 最少路径覆盖

题目链接:http://poj.org/problem?id=1422 Consider a town where all the streets are one-way and each street leads from one intersection to another. It is also known that starting from an intersection and walking through town's streets you can never reach t

hdu 1151 Air Raid (最小路径覆盖)

Air Raid Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3085    Accepted Submission(s): 2004 Problem Description Consider a town where all the streets are one-way and each street leads from on

HDU - 1160 FatMouse&#39;s Speed(dp+路径记录)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1160 题意:给定x组老鼠的重量(W)和速度(S).求使得   W[m[1]] < W[m[2]] < ... < W[m[n]]       S[m[1]] > S[m[2]] > ... > S[m[n]] 的最长序列长度和路径 题解:排序一下,然后LIS,路径记录一下,输出就可以了 1 #include <iostream> 2 #include <a