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);
                }
            }
        }
    }
}
原文地址:https://www.cnblogs.com/tun117/p/5931756.html