Gym 101879C Promenade by the lake —— dfs+并查集 找构成欧拉回路需要添加的边

The city of Porto will host the ICPC World Finals in 2019. One of the secret touristic spots in the city is the so-called “lake of the thousand bridges”. Mr. Manoel Pontes (Pontes stands for “bridges” in Portuguese; this is amazingly his real name…) built this wonder in the lake with a lifetime of hard work. The lake has many small islands. Mr. Manoel built small wooden bridges connecting the islands. In some cases, there are multiple bridges connecting some pairs of islands. Visitors enjoy themselves while promenading through the bridges and small islands. Besides, by walking through the bridges the visitors can go from one island to any other island.

Mr. Manoel wants to enhance this touristic attraction to get even more visitors. One of this ideas is to organize visitors games. He plans to have the following challenge: is it possible to start to walk from outside the lake, pass through all the bridges without repetition, and go back to the starting point (that is, back out of the lake)?

Before creating the attraction, he himself tried it over and over but could not find out if this was possible. To make the challenge even more interesting, Mr. Manoel will allow adding some bridges between some islands. He wants to know if, by adding some of these bridges, the walk he wants the game to have becomes possible. Your task in this problem is to decide if it is possible to choose some (possibly none) of these bridges that, when added, allow people to walk as described.

Input
The first line has three integers N, M and K, where N is the number of islands, M is the number of already built bridges and K is the number of bridges that is possible to add. The islands are represented by distinct integers from 1 to N. Each one of the following M+K lines describes a bridge. Each one of them has two integers, a and b, that represent the existence or possibility of adding a bridge between islands a and b. The first M lines describe bridges that already exist and the next K lines describe bridges that you may add.

Constraints

1≤N≤3⋅105
0≤M,K≤3⋅105
1≤a You may assume that we can go from one island to any other island by using only the bridges already built.
Output
In the first line print “YES” (without the quotes), if such a walk is possible or “NO” otherwise. If there is a solution, print in the second line an integer R, 0≤R≤K that is the number of bridges that need to be added. Next print R lines, each one with two integers, the islands that are connected by this bridge, in any order. If there are multiple solutions, any one will be accepted.

Examples
Input
4 3 4
1 2
2 3
3 4
1 4
1 4
1 3
3 4
Output
YES
1
1 4
Input
4 3 2
1 2
2 3
3 4
1 2
3 4
Output
NO

题意:

给你n个点,m条已经连成的边和k条可选边,问你需要从k里面取出那些才能构成一个欧拉回路

题解:

欧拉回路就是从起点开始每条边都走一遍最后回到起点,由此可以推出所有边的度都是偶数的。
易证如果可以通过添加边来构成欧拉回路那么奇数边的点一定是偶数个。
接下来怎么找有哪些边呢,我们可以知道如果有一条可选边的左右奇数顶点是奇数个的,那么这条边一定要连,因为两块内部可能无法自己连成欧拉回路,原因刚才讲过了,如果这条边左右是偶数的话,那么这条边就不用连,举个例子:1-2-3-4和5-2-3-6,那么1-2-5和4-3-6就可以连起来,不再需要2-3这条边,那么我们for一遍所有点并dfs即可。

#include
using namespace std;
#define pa pair
#define mp(a,b) make_pair(a,b)
const int N=3e5+5;
int fa[N],num[N],ctans;
pa ans[N];
struct node
{
    int to,next;
}e[N*2];
int head[N],cnt;
void add(int x,int y)
{
    e[cnt].to=y;
    e[cnt].next=head[x];
    head[x]=cnt++;
}
int finds(int x)
{
    return x==fa[x]?fa[x]:fa[x]=finds(fa[x]);
}
int siz[N];
void match(int x,int y)
{
    int fax=finds(x);
    int fay=finds(y);
    if(fax!=fay)
    {
        fa[fay]=fax;
        siz[fax]+=siz[fay];
    }
}
int vis[N];
void dfs(int f)
{
    vis[f]=1;
    for(int i=head[f];~i;i=e[i].next)
    {
        int son=e[i].to;
        if(!vis[son])
        {
            dfs(son);
            num[f]+=num[son];
            if(num[son]%2)
                ans[++ctans]=mp(f,son);
        }
    }
}
int main()
{
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    memset(head,-1,sizeof(head));
    int f,s;
    for(int i=1;i<=n;i++)
        fa[i]=i,num[i]=0;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&f,&s);
        num[f]++,num[s]++;
    }
    for(int i=1;i<=n;i++)
        siz[i]=num[i];
    for(int i=1;i<=k;i++)
    {
        scanf("%d%d",&f,&s);
        add(f,s),add(s,f),match(f,s);
    }
    //for(int i=1;i<=n;i++)
        //cout<

你可能感兴趣的:(dfs,想法,欧拉路径)