• [JCWC2005]Draw


    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.
    View Code

     

  • 相关阅读:
    Java_File类
    Java_Math类和Random类
    Java_包装类
    Java_Stringbuilder和StringBuffer
    Java_String
    Java_数组, 懒得整理了 ---------------------> 未完, 待续
    Java_内部类
    Java_三大特征相关
    Java_垃圾回收机制(未掌握)
    重载(overload)和重写(override)的区别?
  • 原文地址:https://www.cnblogs.com/yangqingli/p/4907412.html
Copyright © 2020-2023  润新知