最小生成樹好題。
下面規定鵝卵石路長度為 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...