[JCWC2005]Draw
2015-10-24 19:20
260 查看
Einstein学起了画画,
此人比较懒~~,他希望用最少的笔画画出一张画。。。
给定一个无向图,包含 n 个顶点(编号1~n),m 条边,求最少用多少笔可以画出图
中所有的边
以下m行每行 2个数a,b(a<>b) 表示a,b两点之间有一条边相连
一条边不会被描述多次
5 5
2 3
2 4
2 5
3 4
4 5
output
1
100%的数据n<=1000,m<=100000
■⒈凡是由偶点组成的连通图,一定可以一笔画成。画时可以把任一偶点为起点,最后一定能以这个点为终点画完此图。
■⒉凡是只有两个奇点的连通图(其余都为偶点),一定可以一笔画成。画时必须把一个奇点为起点,另一个奇点终点。
■⒊其他情况的图都不能一笔画出。(奇点数除以二便可算出此图需几笔画成。)
再比如这个例子,单纯的按照一般的算法写出来答案是1,显然答案是2,所以要统计输入数据中联通图的数量,再分别进行求解。并查集可以实现。
View Code
此人比较懒~~,他希望用最少的笔画画出一张画。。。
给定一个无向图,包含 n 个顶点(编号1~n),m 条边,求最少用多少笔可以画出图
中所有的边
Input (draw.in)
第一行2个数n,m以下m行每行 2个数a,b(a<>b) 表示a,b两点之间有一条边相连
一条边不会被描述多次
Output (draw.out)
一个数即问题的答案Sample
Input5 5
2 3
2 4
2 5
3 4
4 5
output
1
约定
50%的数据n<=50,m<=100100%的数据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.
View Code
相关文章推荐
- 写一个Windows上的守护进程(1)开篇
- 【PAT】1102. Invert a Binary Tree (25)
- 黑马程序员——————泛型的使用与Map的初步学习
- Java基础(3)----选择与循环语句
- UML之用例图
- Java基础程序设计---数据类型
- [深入理解Java虚拟机]第七章 类加载的过程
- linux下ElasticSearch安装部署
- 2015-2016 ACM-ICPC, NEERC, Moscow Subregional Contest A题:Anagrams [打表/规律题]
- 关于javascript中this的理解
- className.class.getResourceAsStream()与ClassLoader.getSystemResourceAsStream() 的区别
- C++对象模型——默认构造函数的合成
- Java概述及JDK的安装
- C++的几个知识点
- 转发和重定向 方法的使用
- ACM学习历程—HDU 5072 Coprime(容斥原理)
- VC++ 在控件上写字时 字体的设置技巧
- (NO.00001)iOS游戏SpeedBoy Lite成形记(十五)
- hdu5495
- hihocoder 1039 字符消除