zoukankan      html  css  js  c++  java
  • hdu6311 /// 欧拉路径 无向图最小路径覆盖 输出正反路径

    题目大意:

    给定n m 为图的点数和边数

    接下来m行 u v 为u到v有一条边

    要求最少几笔能画完图的所有边

    输出每笔画过的路径编号 正数编号正向 负数编号反向

    题解:https://www.cnblogs.com/xiuwenli/p/9372062.html

    #include <bits/stdc++.h>
    #define INF 0x3f3f3f3f
    #define LL long long
    #define mem(i,j) memset(i,j,sizeof(i))
    using namespace std;
    const int N=1e5+5;
    int n, m;
    struct EDGE {
        int to,nt; int id; bool f;
    }E[N<<4];
    int head[N], tot;
    void addE(int u,int v,int id) {
        E[tot].f=0; E[tot].to=v;
        E[tot].id=id; E[tot].nt=head[u];
        head[u]=tot++;
    }
    bool vis[N];
    int deg[N], cnt;
    vector <int> ans[N];
    void init() {
        tot=cnt=0; mem(head,-1);
        mem(deg,0); mem(vis,0);
    }
    
    void dfs(int u) {
        vis[u]=1;
        for(int i=head[u];~i;i=E[i].nt) {
            int v=E[i].to, id=E[i].id;
            if(!E[i].f) {
                E[i].f=E[i^1].f=1; // 这条边和对应的反向边标记
                dfs(v); // 一直搜到终点
                if(id) ans[cnt].push_back(-id); // 从终点开始反向记录路径 所以是-id
                else cnt++; // id为0说明遇到了手动加的边 就是新的一笔
            }
        }
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&m)) {
            init();
            for(int i=1;i<=m;i++) {
                int u,v; scanf("%d%d",&u,&v);
                deg[u]++, deg[v]++;
                addE(u,v,i); addE(v,u,-i);
            }
    
            int u=0;
            for(int i=1;i<=n;i++)
                if(deg[i]&1) { // 奇数度的点 两两连边
                    if(u) addE(u,i,0), addE(i,u,0), u=0; 
                    else u=i;
                }
    
            for(int i=1;i<=n;i++)
                if(!vis[i] && (deg[i]&1)) { /// 先从奇数点开始搜
                    cnt++; dfs(i); cnt--; // cnt记录的是之前的最后一条路
                } 
            // 所以记录新的路应该cnt++先移到下一条路
            // 搜索过程中一直cnt++所以搜索结束后cnt是在下一条路
            // 此时将cnt置为最后一条路 应该cnt--
            for(int i=1;i<=n;i++)
                if(!vis[i] && deg[i]) {
                    cnt++; dfs(i);
                } // 此时还未走过的点都是偶数点 形成一个环 所以不需要cnt--
    
            printf("%d
    ",cnt);
            for(int i=1;i<=cnt;i++) {
                int len=ans[i].size();
                printf("%d",len);
                for(int j=0;j<len;j++)
                    printf(" %d",ans[i][j]);
                printf("
    "); ans[i].clear();
            }
        }
    
        return 0;
    }            
    View Code
  • 相关阅读:
    C#值类型和引用类型的不同
    C# new用法总结-转
    C#中New关键词的几种用法
    命令行客户端MySQL的使用(1)——Python
    数据库的基本使用——MySQL
    生成器的创建方式——Python
    with与“上下文管理器”——Python
    魔法属性——Python
    property属性——Python
    正则匹配之贪婪和非贪婪——Python
  • 原文地址:https://www.cnblogs.com/zquzjx/p/10312662.html
Copyright © 2011-2022 走看看