CSP马上到了,赶紧复习图论,顺便写下题解

题目要使画的次数最小,那么我们就可以知道最小的次数为1

于是这道题就是一笔画(欧拉路)板题,甚至还不需要求路径。

先来说一下什么是欧拉路吧:

七桥问题

欧拉说:是否可从某个地方出发,经过每座桥一次,回到原来出发的地方?

然后七桥问题就能转化成如下的一个无向图

顶点的度,就是指和该顶点相关联的边数。

出度:有向图中从某顶点出发的边数。

入度:有向图中在某顶点结束的边数。

欧拉回路:

若恰通过图中每条边一次回到起点,则称该回路为欧拉(Euler)回路。
具有欧拉回路的图称为欧拉图。
定理1:
一个无向图是欧拉图,当且仅当该图所有顶点度数都是偶数。
一个有向图是欧拉图,当且仅当该图所有顶点度数都是0(入度与出度之和)。
定理2:
存在欧拉回路的条件:图是连通的,且不存在奇点(顶点度数为奇数)

欧拉路(此题解法 !)

若从起点到终点的路径恰通过图中每条边一次(起点与终点是不同的点),
则该路径称为欧拉路。
定理1:
存在欧拉路的条件:图是连通的,且存在2个奇点。
如果存在2个奇点,则欧拉路一定是从一个奇点出发,以另一个奇点结束。

注意:一个连通图只可能有偶数个奇点

那么我们可以从欧拉路的介绍,发现只有2个奇点才能1笔画完。

#include<bits/stdc++.h>
using namespace std;
int n,m,cnt[1005],ans;
cnt[x]:x的度数
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d %d",&x,&y);
        cnt[x]++;x点度数+1
        cnt[y]++;y点度数+1
    }
    for(int i=1;i<=n;i++)
        if(cnt[i]%2)判断是否为奇点
            ans++;奇点个数+1
    if(ans==2)若只有2个奇点
        puts("1");则可以一笔画完
    return 0;
}

现在我们已经知道如何判断欧拉路了

然后我们可以发现若每多出两个奇点,那么画的次数就会+1

又因为连通图只可能有偶数个奇点

所以,答案为

#include<bits/stdc++.h>
using namespace std;
int n,m,cnt[1005],ans;
cnt[x]:x的度数
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d %d",&x,&y);
        cnt[x]++;x点度数+1
        cnt[y]++;y点度数+1
    }
    for(int i=1;i<=n;i++)
        if(cnt[i]%2)判断是否为奇点
            ans++;奇点个数+1
    printf("%d\n",ans/2);
    return 0;
}

于是我们愉快的交了上去,WA90。。。。。

这是为什么呢??

根据我们上面的做法,发现下列手购数据过不了:

3 3
1 2
2 3
3 1

利用构图我们可以得到这幅图:

咦,发现这3个点都不是奇数点,但也可以一笔画完,所以我们只需要特判一下即可AC

#include<bits/stdc++.h>上面代码已经有注释了,就不打了qwq
using namespace std;
int n,m,cnt[1005],ans;
int main(){
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d %d",&x,&y);
        cnt[x]++;
        cnt[y]++;
    }
    for(int i=1;i<=n;i++){
        if(cnt[i]&1==1)
            ans++;
    }
    if(ans==0)
        puts("1");
    else
        printf("%d\n",ans/2);
    return 0;
}