Einstein学起了画画,
此人比较懒~~,他希望用最少的笔画画出一张画。。。
给定一个无向图,包含 n 个顶点(编号1~n),m 条边,求最少用多少笔可以画出图
中所有的边
Input (draw.in)
第一行2个数n,m
以下m行每行 2个数a,b(a<>b) 表示a,b两点之间有一条边相连
一条边不会被描述多次
Output (draw.out)
一个数即问题的答案
Sample
Input
5 5
2 3
2 4
2 5
3 4
4 5
output
1
约定
50%的数据n<=50,m<=100
100%的数据n<=1000,m<=100000
思路
求一个无向图中有几个哈密尔顿路。也是求边的一笔画问题。
概念补充
奇点就是从这个点出发的线有奇数条,偶点就是从这个点出发的线有偶数条.
关键部分
如何判断一个图形是否可以一笔不重地画出
■⒈凡是由偶点组成的连通图,一定可以一笔画成。画时可以把任一偶点为起点,最后一定能以这个点为终点画完此图。
■⒉凡是只有两个奇点的连通图(其余都为偶点),一定可以一笔画成。画时必须把一个奇点为起点,另一个奇点终点。
■⒊其他情况的图都不能一笔画出。(奇点数除以二便可算出此图需几笔画成。)
易错点
注意此题可能图不是联通的,由样例就可以看出它是一个单独的点加上一个连通图。
再比如这个例子,单纯的按照一般的算法写出来答案是1,显然答案是2,所以要统计输入数据中联通图的数量,再分别进行求解。并查集可以实现。
var n,m,i,u,v,sum1,sum2,mid:longint; b,f:array[0..1010] of longint; procedure intt; begin assign(input,'draw.in'); assign(output,'draw.out'); reset(input); rewrite(output); end; procedure outt; begin close(input); close(output); end; procedure sort(l,r: longint); var i,j,x,y: longint; begin i:=l; j:=r; x:=f[(l+r) div 2]; repeat while f[i]<x do inc(i); while x<f[j] do dec(j); if not(i>j) then begin y:=f[i]; f[i]:=f[j]; f[j]:=y; y:=b[i]; b[i]:=b[j]; b[j]:=y; inc(i); j:=j-1; end; until i>j; if l<j then sort(l,j); if i<r then sort(i,r); end; function root(x:longint):Longint; begin if f[x]=x then exit(x) else root:=root(f[x]); f[x]:=root; exit(root); end; begin intt; readln(n,m); for i:=1 to n do f[i]:=i; for i:=1 to m do begin read(u,v); if root(u)<>root(v) then f[root(u)]:=root(v); inc(b[u]); inc(b[v]); end; for i:=1 to n do mid:=root(i); sort(1,n); v:=n; while v>1 do begin while f[v-1]<>f[v] do dec(v); inc(sum2); mid:=f[v]; while f[v]=mid do begin if b[v] mod 2=1 then inc(sum1); dec(v); end; if sum1>0 then sum1:=sum1-2; sum2:=sum2+sum1 div 2; sum1:=0; end; writeln((sum1 div 2)+sum2); outt; end.