hdu3018 一笔画问题
? ? ? 給你一幅畫,這幅畫由點(diǎn)和邊構(gòu)成,問(wèn)你最少幾筆能把這幅畫畫完。
思路:
? ? ?這個(gè)題目的結(jié)論比較巧妙,首先我們考慮下,如果給的圖是歐拉圖,或者是條歐拉回路,那么我們一筆就搞定了,那么我們可以把圖的每一個(gè)部分<聯(lián)通快>都檢查一遍,如果是
連通塊,那么就直接+1,如果不是歐拉回路<包括歐拉路>,那么我們就要統(tǒng)計(jì)這個(gè)連通塊的度數(shù)為奇數(shù)的點(diǎn)的個(gè)數(shù)s, 答案+s/2,原因是我們可以用s/2筆把所有的奇數(shù)度都填充完,一次填充兩個(gè),當(dāng)最后一筆的時(shí)候整個(gè)連通塊已經(jīng)是一個(gè)歐拉回路了,然后我們必要把最后一筆抬起來(lái),直接一筆畫就行了,還有就是提示下s永遠(yuǎn)都是偶數(shù),因?yàn)槊慨?dāng)添加一筆的時(shí)候有四種情況新添加的這條邊的兩個(gè)端點(diǎn) 分別產(chǎn)生兩個(gè)度數(shù)為奇數(shù)的 + 2 分別消除兩個(gè)度數(shù)為奇數(shù)的 -2 分別一個(gè)消除,一個(gè)增加 +1-1 所以買個(gè)連通塊的奇數(shù)度點(diǎn)的個(gè)數(shù)很定是偶數(shù)個(gè),總之最優(yōu)的策略就是用最少的步數(shù)把每個(gè)一個(gè)連通塊變成歐拉回路,然后一筆搞定,還有就是要明確,我們并不是在填邊,而是說(shuō)需要填邊的地方就是我們臺(tái)筆的地方,也就是要多花費(fèi)一筆的地方。還有提示一點(diǎn),可能出現(xiàn)獨(dú)立的一個(gè)點(diǎn),獨(dú)立的點(diǎn)不用畫,其他的具體細(xì)節(jié)看代碼。
#include<stdio.h> #include<string.h>#define N_node 110000 #define N_edge 110000 typedef struct {int to ,next; }STAR;STAR E[N_edge]; int list[N_node] ,tot; int mer[N_node] ,du[N_node];void add(int a ,int b) {E[++tot].to = b;E[tot].next = list[a];list[a] = tot; }int finds(int x) {return x == mer[x] ? x : mer[x] = finds(mer[x]); }int main () {int i ,j ,n ,m ,a ,b;while(~scanf("%d %d" ,&n ,&m)){for(i = 1 ;i <= n ;i ++) mer[i] = i;memset(du ,0 ,sizeof(du));for(i = 1 ;i <= m ;i ++){scanf("%d %d" ,&a ,&b);mer[finds(a)] = finds(b);du[a] ++ ,du[b] ++;}memset(list ,0 ,sizeof(list)) ,tot = 1;for(i = 1 ;i <= n ;i ++){int x = finds(i);if(x == i) continue;add(x ,i);}int Ans = 0;for(i = 1 ;i <= n ;i ++){int tsum = 0;int x = finds(i);if(i != x || i == x && !list[x]) continue;tsum = du[i] % 2;for(int k = list[x] ;k ;k = E[k].next)tsum += du[E[k].to] % 2;(!tsum)? tsum ++ : tsum /= 2;Ans += tsum;}printf("%d\n" ,Ans);}return 0; }
總結(jié)
以上是生活随笔為你收集整理的hdu3018 一笔画问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: POJ2553 强连通出度为0的应用
- 下一篇: hdu3472 混合欧拉