HDU 2242 考研路茫茫 空調教室

2021-09-06 04:35:38 字數 2532 閱讀 1777

hdu_2242

這個題目首先可以求出邊雙連通分量並進行縮點,如果邊雙連通分量的個數只有乙個的話就必然無解,之後我們把縮好的點建成乙個新圖,這個圖實際上就是一棵樹。

如果我們隨便找個點當做樹根,並把圖畫成樹形結構的話,就會發現實際上我們只要求出除樹根外每個節點以及其下方的所有節點的權值和即可,每求出乙個權值和,就算一下人數差並更新一下min。同時,為了充分利用子問題的解,我們在計算結果的時候可以採用dfs的方式,每個節點返回自己以及自己下方的所有節點的權值和。

需要說明的是,由於這個題目存在兩點之間有多條邊的情況,於是在用tarjan時就要判斷一下當前掃瞄的邊是否是之前來到這個節點的邊的反向邊。

我之前在codeforces做過乙個題目,就是乙個tarjan和乙個dfs去解,並且由於tarjan本質上就是dfs,於是便用一定手段把兩個dfs優化成了乙個。想到這裡,我又不禁想到,這道題目的tarjan和dfs是否可以優化成乙個dfs呢?研究了之後,發現確實可以。

我們可以這麼想,最後縮點之後每個點的點權實際上不就是該雙連通分量裡的所有點的點權和麼?而再想想縮點之後dfs計算的過程,實際上是不斷計算子問題的解並向上傳遞值的過程,傳遞值的過程不就是相當於把所有子節點的值累加給父節點麼?

有了這些想法之後,我們每次在找到橋u->v後,在彈棧的過程中,可以把彈出的所有點的點權和算出來,並用這個和更新min,之後再把這個和累加給u即可。這樣,tarjan和dfs就合併成了乙個dfs的過程了。

/*

tarjan + dfs,未優化

*/#include

#include

#include

#define maxd 10010

#define maxm 80010

int m, n, people[maxd];

int gfirst[maxd], gfirst[maxd];

int gnext[maxm], gnext[maxm];

int gv[maxm], gv[maxm], ge, ge;

int dfn[maxd], low[maxd], s[maxd], top, cnt;

int col, color[maxd], sum[maxd], min, total, vis[maxd];

void gadd(int x, int y)

void gadd(int x, int y)

void init()

}void tarjan(int u, int fa)

col ++;}}

else

if(dfn[gv[i]] < low[u])

low[u] = dfn[gv[i]];}}

int dfs(int u)

return a + sum[u];

}void solve()

memset(sum, 0, sizeof(sum));

total = 0;

for(i = 0; i < n; i ++)

memset(gfirst, -1, sizeof(gfirst));

ge = 0;

for(i = 0; i < n; i ++)

for(j = gfirst[i]; j != -1; j = gnext[j])

if(color[i] != color[gv[j]])

min = 0x7fffffff;

memset(vis, 0, sizeof(vis));

dfs(0);

printf("

%d\n

", min);

}int main()

return

0;}

/*

優化成了乙個dfs

*/#include

#include

#include

#define maxd 10010

#define maxm 40010

int m, n, people[maxd];

int first[maxd], next[maxm], v[maxm], e;

int dfn[maxd], low[maxd], s[maxd], top, cnt, min, total, col;

void add(int x, int y)

void init()

memset(first, -1, sizeof(first));

e = 0;

for(i = 0; i < m; i ++)

}void tarjan(int u, int fa)

col ++;

if(abs(total - 2 * temp) < min)

min = abs(total - 2 * temp);

people[u] += temp;}}

else

if(dfn[v[i]] < low[u])

low[u] = dfn[v[i]];}}

void solve()

int main()

return

0;}

HDU 2242(考研路茫茫 空調教室)

題意 有乙個教室群,教室之間有空調管相連 原圖連通 每個教室都有人,求斷開一條空調管使之分開成兩個教室群,並且使兩個教師群的人數差值最小。思路 這題沒什麼難度吧。思路都很明了 可能是看過標籤的緣故吧0.0 求邊雙連通分量,縮點,然後進行樹形dp計數求出答案即可,貼個 以後拿來當模板用吧。includ...

hdu 2242 考研路茫茫 空調教室

題意 給乙個雙聯通圖 有重邊 每乙個節點有權值,現在要求把以一條邊去掉,使得這個圖分為兩個部分,而且要使得這兩個部分的權的差的絕對值最小 思路 1,邊 雙連通求縮點,得到一顆樹 2,簡單樹形dp 這題難倒我好久,首先是各種hash使得mle,然後就是陣列開小了,沒有注意m的值有2w 最重大錯誤就在於...

HDU 2242 考研路茫茫 空調教室

眾所周知,hdu的考研教室是沒有空調的,於是就苦了不少不去圖書館的考研仔們。lele也是其中乙個。而某教室旁邊又擺著兩個未裝上的空調,更是引起人們無限yy。乙個炎熱的下午,lele照例在教室睡覺的時候,竟然做起了空調教室的美夢。lele夢到學校某天終於大發慈悲給某個教室安上了乙個空調。而且建造了了m...