zoukankan      html  css  js  c++  java
  • Codeforces 723e [图论][欧拉回路]

    /*
    不要低头,不要放弃,不要气馁,不要慌张。
    题意:
    给你一个有n个点,m条边的无向图,给每条边规定一个方向,使得这个图变成有向图,并且使得尽可能多的点入度与出度相同。
    输出有多少个这样的点并且输出有向图。
    思路:
    1.针对每个连通分支。
    2.所有点入度与出度相同,显然这是欧拉回路存在的判定定理,但是欧拉回路的另外一个等价定理是所有点的度数是偶数。那如果给我们的图中的某些点是奇数度该怎么办。
    3.显然原图中给的点如果度数是奇数,那么该点的入度与出度一定不相同。
    4.根据握手定理,无向图中度数是奇数的点一定是偶数个,所以我们可以尝试对任一连通分支增加一个点,该点与所有该联通分支中奇数点连接一条边,显然该图可以找到一条欧拉回路。
    5.将图构建好之后,寻找一条欧拉回路....问题解决...
    
    
    坑:
    wa在图的构建上,没有想到可以加一个点...还是很弱...
    
    */
    #include<bits/stdc++.h>
    #define N 1000
    #define M 100000
    using namespace std;
    int id[N];
    int findme(int a){
        if(id[a]!=a)return id[a]=findme(id[a]);
        return a;
    }
    bool vis[N][N];
    bool vvis[N];
    bool vvv[N][N];
    bool iii[N];
    struct edge{
        bool rel,im,vis;
        int id;
        edge *next;
    };
    edge edges[M<<1];
    edge *adj[N];
    int num[N];
    int ednum;
    inline void addedge(int a,int b,bool c){
        edge *tmp=&edges[ednum++];
        tmp->im=c;
        tmp->rel=0;
        tmp->vis=0;
        tmp->id=b;
        tmp->next=adj[a];
        adj[a]=tmp;
    }
    vector<int>mv;
    void dfs(int pos){
        vvis[pos]=1;
        for(edge *it=adj[pos];it;it=it->next){
            if(vis[pos][it->id]==0&&it->vis==0){
                vis[pos][it->id]=1;
                vis[it->id][pos]=1;
                it->vis=1;
                dfs(it->id);
            }
        }
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--){
            memset(iii,0,sizeof(iii));
            memset(vvv,0,sizeof(vvv));
            memset(vvis,0,sizeof(vvis));
            memset(vis,0,sizeof(vis));
            memset(num,0,sizeof(num));
            memset(adj,0,sizeof(adj));
            ednum=0;
            int n,m;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)id[i]=i;
            for(int i=1;i<=m;i++){
                int a,b;
                scanf("%d%d",&a,&b);
                int aa=findme(a);
                int bb=findme(b);
                if(aa!=bb)id[aa]=bb;
                addedge(a,b,1);
                addedge(b,a,1);
                num[a]++;
                num[b]++;
                vvv[a][b]=vvv[b][a]=1;
            }
            mv.clear();
            for(int i=1;i<=n;i++){
                if(num[i]&1)mv.push_back(i);
            }
            int w=mv.size();
            for(int i=0;i<w;i++){
                addedge(mv[i],n+findme(mv[i]),0);
                addedge(n+findme(mv[i]),mv[i],0);
            }
            for(int i=1;i<=n;i++){
                if(!vvis[i])dfs(i);
            }
            printf("%d
    ",n-mv.size());
            for(int i=1;i<=n;i++){
                for(edge *it=adj[i];it;it=it->next){
                    if(it->im&&it->vis){
                        printf("%d %d
    ",i,it->id);
                    }
                }
            }
        }
    }
  • 相关阅读:
    InnoDB实现MVCC原理
    Python中定义函数时参数有默认值的小陷阱
    Python系统编程笔记
    Python中的字典
    Python中常见的字符串小笔试题
    Oracle常见名词解析
    Oracle数据库面试题【转载】
    Oracle日期语言修改
    Oracle日期时间函数大全
    Oracle数据库分页的三种方法
  • 原文地址:https://www.cnblogs.com/tun117/p/5931756.html
Copyright © 2011-2022 走看看