P3623 APIO2008 免費道路 題解

2022-10-09 23:33:18 字數 1374 閱讀 6745

最小生成樹好題。

下面規定鵝卵石路長度為 1,水泥路長度為 0,則題中要求的是一棵邊權為 \(k\) 的生成樹。

這道題一開始的時候我會認為邊權為 1 的邊可以隨便加,畢竟根據樣例來看,刪這一條換另一條並沒有什麼問題。

於是就有一種做法是先選好 \(k\) 條 1 邊,然後剩下的 0 邊隨意加。

然而根據下面這張圖,你就會發現上述做法有問題:

如果此時 \(k=1\),而你又挑選了 \((1,3)\) 的話……

此時圖根本不連通!

因此,有一些邊是一定要加的。

那麼怎麼知道哪些邊一定要加呢?

考慮對圖做一遍最小生成樹,記錄一下加入到最小生成樹的 1 邊數量,這些 1 邊就是一定要加的,因為如果刪了這些邊就不合法了。

然後呢?先加入這些必須加的 1 邊,然後在剩下的所有 1 邊中加邊直到加滿,這些邊是可以隨便選的。最後拿 0 邊補齊即可。

無解情況:

**:

/*

*****==== plozia *****====

author:plozia

problem:p3623 [apio2008]免費道路

date:2021/4/22

*****==== plozia *****====

*/#include typedef long long ll;

const int maxn = 20000 + 10, maxm = 100000 + 10;

int n, m, k;

struct node a[maxm];

struct union

int gf(int x)

void hb(int x, int y)

}u;int read()

bool cmp1(const node &fir, const node &sec)

bool cmp2(const node &fir, const node &sec)

int main()

}if (tmp > k)

if (sum != 1)

std::sort(a + 1, a + m + 1, cmp2);

u.init(); sum = n;

for (int i = 1; i <= m; ++i)

if (a[i].z == -1)

for (int i = 1; i <= m; ++i)

}if (tmp != k)

for (int i = 1; i <= m; ++i)

return 0;

}

APIO2008 免費道路

bzoj luogu 先把必須連的鵝卵石路連上,大於k條no solution 什麼樣的鵝卵石路 u,v 必須連?所有水泥路都連上仍然不能使u,v連通的必須連 補全到k條鵝卵石路,補不全no solution 最後用水泥路構出生成樹,構不出no solution includeusing names...

APIO2008 免費道路

kruskal 好題 0 邊的數量在某些情況下是可以無限制的調控的,前提是所有必須存在的邊都在生成樹里了 所以應該分別求出有哪些邊是必須在生成樹里的,我們可以先從大到小排序,求出有哪些 0 邊必須在生成樹里,之後再從小到大排序,求出那些 1 邊必須在生成樹里 之後剩下的邊就可以隨便放了,調控 0 邊...

3624 Apio2008 免費道路

題解 這題是要求乙個生成樹,要求生成樹中要有k條石子路。我們一開始先盡量讓生成樹里多一點水泥路,這樣就可以知道哪些石子路是必須要的。如果必須要的多於k,則無解。然後再把一些水泥路換成石子路,接著再判判無解。include include include include includeusing na...