nyoj42 一笔画问题

来源:互联网 发布:网络炒股的人多吗 编辑:程序博客网 时间:2024/05/09 08:27

题目链接
分析:

若图G中存在这样一条路径,使得它恰通过G中每条边一次,则称该路径为欧拉路径。若该路径是一个圈,则称为欧拉(Euler)回路。
具有欧拉回路的图称为欧拉图(简称E图)。具有欧拉路径但不具有欧拉回路的图称为半欧拉图。

先说一下欧拉路径、欧拉回路的充要条件:
1.无向连通图G是欧拉图,当且仅当G不含奇数度结点(G的所有结点度数为偶数);
2.无向连通图G含有欧拉通路,当且仅当G有零个或两个奇数度的结点;
3.有向连通图D是欧拉图,当且仅当该图为连通图且D中每个结点的入度=出度
4.有向连通图D含有欧拉通路,当且仅当该图为连通图且D中除两个结点外,其余每个结点的入度=出度,且此两点满足deg-(u)-deg+(v)=±1。(起始点s的入度=出度-1,结束点t的出度=入度-1 或两个点的入度=出度)
5.一个非平凡连通图是欧拉图当且仅当它的每条边属于奇数个环。

而我们这道题一笔画, 正是要经过图中的每条边一次。 也就是说我们判断一下所个图是否存在欧拉路径就可以啦。 首先求图是否连通(判断连通我们用并查集就好啦, 简单、易懂), 再判断图是否存在欧拉路径(所有点度数为偶数或者只有两个点度数为奇数,其它均为偶数)。

还有注意输出的是 Yes / No

#include<iostream>#include<cstdio>#include<string.h>#include<cstring>#include<vector>using namespace std;int t, n, m, sum, pre[1010], du[1010], v[1010][1010];int find(int x){    int i, j, r;    i = x; r = x;    while(r != pre[r])        r = pre[r];    while(pre[i] != r)    {        j = pre[i];        pre[i] = r;        i = j;    }    return pre[x];}int main(){    cin >> t;    while(t--)    {        scanf("%d%d", &n, &m);        memset(v, 0, sizeof(v));        memset(du, 0, sizeof(du));        for(int i = 1; i <= n; i++) pre[i] = i;        for(int i = 1; i <= m; i++)        {            int x, y;            scanf("%d%d", &x, &y);            int fx = find(x);            int fy = find(y);            if(fx != fy)                pre[fx] = fy;            if(v[x][y] == 0)            {                v[x][y] = 1;                v[y][x] = 1;                du[x]++;//记录度数                du[y]++;            }        }        int ans = find(1);        int flag = 1;        for(int i = 2; i <= n; i++)// 判断是否是连通图        {            int fx = find(i);            if(fx != ans)              {                flag = 0;                break;            }        }        sum = 0;        if(flag == 1)        {            for(int i = 1; i <= n; i++)// 若是连通图, 再判断节点度数为奇数共有几个            {                if(du[i] % 2 == 1)                    sum++;            }            if(sum == 0 || sum == 2)                printf("Yes\n");            else                printf("No\n");        }        else            printf("No\n");    }    return 0;}
0 0