最小度限制生成樹

2021-08-31 17:19:17 字數 2993 閱讀 3308

在一棵生成樹中,某個頂點v0的度數<=k稱作度限制條件,把滿足這一條件的生成樹稱為度限制生成樹,把權值和最小的度限制生成樹稱為最小度限制生成樹

如果撇開度限制條件,那麼就是最小生成樹問題。首先,避開度限制條件。假如把最小度限制生成樹中所有與v0相關的邊都刪掉,得到m個連通分量。

具體步驟:

1. 如果k

2. 求最小m度限制生成樹。

3. 有最小m度限制生成樹求最小m+1度限制生成樹。

4. 當dt(v0)==k時,停止迭代。

說明:

求最小m度限制生成樹時:去掉圖中和v0相連的所有邊,得到m個連通分量,而這m個連通分量必須通過v0來連線。所以在生成樹中,dt(v0)>=m,如果k

由最小m度限制生成樹得到最小m+1度限制生成樹:對於和v0相鄰的點v,新增後一定會形成乙個環,找到環上權值最大的邊,用(v0,v)替換掉。列舉所有和v0相鄰的點,找到權值增加最小的一次替換,就可以得到最小m+1度限制生成樹。每次列舉的時候都需要找換上不和v0相連的最大邊,需要用到動態規劃:設best[v]是v0到v路勁上不與v0相連的最大邊,定義father[v]是v的父節點,狀態轉移方程為:

best[v] = max

邊界條件為best[v0]=inf,best[v']=inf((v0,v')是圖中的邊)。

模型與例題:

1. 考慮下面這個問題:

問怎樣合理的分配衛星和鋪設線路,使得任意兩個村莊都能直接或間接通訊,並且鋪設線路最短,求最短的線路是多少。n,k<=5000

解:如果不設衛星,就相當於求原圖的最小生成樹。如何改造該模型?增設乙個點v0,和所有村莊相連,權值為0,該圖的乙個最小生成樹就對應著一種方案,鋪設路線長度為對應的生成樹的權值之和,生成樹中與v0相關的村莊為安放衛星的村莊。這樣問題轉化為求dt(v0)==k的最小生成樹問題了。

2. poj1639

題意:一些人準備去公園開party,每個人可以開車直接去或者把車開到a家,然後做a的車到公園,每輛車可以座無數個人,但公園最多只能停放k輛車。問所有人開車的路程之和最短為多少。

解:把公園點v0看成度限制條件,求所有<=k的度限制生成樹,取最小值即可。

/*

最小度限制生成樹

*/#include #include #include using namespace std;

const int inf = 0x7fffffff;

const int n = 30;

int n,s,k; //節點總數 有度數限制的點v0 度數限制為k

int mst; //最終結果:最小k限制度生成樹

int mp[n][n]; //圖

int father[n]; //節點n的父節點

bool edge[n][n]; //判斷邊(i,j)是否加入到生成樹中

int best[n]; //從v0到v路徑上與v0無關的最大權邊的點序號

char str[n][12];

int dis[n];

bool mark[n];

bool vis[n];

int pre[n];

void dfs(int now)

}}int prim(int s) //從點s開始的最小生成樹

while(true)

}if(min == inf) break;

mark[key] = true;

vis[key] = true;

edge[pre[key]][key] = edge[key][pre[key]] = true;

sum += min;

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

min = inf;

int root = -1; //找到與v0相關聯的點的最小邊

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

}mark[root] = false;

dfs(root); // 將樹拉成有根樹

father[root] = s;

return sum + min;

}int best(int x) //記憶化搜尋s到x的最大權值的邊

int find(char *c)

return -1;

}void input()

int y = find(s2);

if(y == -1)

if(w < mp[x][y]) //可能有重邊

mp[x][y] = mp[y][x] = w;

}scanf("%d",&k);

}void solve()

}int change; // 回路上權值最大的邊,用於交換

int ax,bx,tmp;

for(i = m+1; i <= k && i < n; i++)

int minadd = inf; // 交換邊的最小差值

for(j = 0; j < n; j++)}}

if (minadd >= 0) break; //用於度數不大於k的限制,如果k限制,就不用break了

mst += minadd;

ax = best[change];

bx = father[ax];

mp[ax][bx] = mp[bx][ax] = inf;

father[ax] = bx = s; // 改變生成樹,將點ax直接指向源點s

mp[ax][s] = mp[s][ax] = mp[change][s];

mp[s][change] = mp[change][s] = inf;

}}int main()

最小度限制生成樹

最小度限制生成樹 具體講解和證明,黑書上有,ioi2004國家集訓隊 王汀 中也有講解,這裡簡單介紹求法過程。為了方便敘述,把頂點v0的度數 k稱作度限制條件,把滿足這一條件的生成樹稱為度限制生成樹,把權值和最小的度限制生成樹稱為最小度限制生成樹。要求的最小k度生成樹,應該有以下的步驟 演算法框架 ...

最小度限制生成樹

黑書 各種資料。終於理解了一點。最小度限制生成樹就是給乙個圖,讓求它的最小生成樹。找的的最小生成樹滿足並且點vo的度最大為k。演算法流程如下 1.將該點 以下用v0表示 從圖中刪除,將得到m個連通分量。2.對每個連通分量求最小生成樹,假設m個。3.從每個連通分量中找與v0關聯的權值最小的邊,與v0相...

ACM 最小度限制生成樹

最小度限制生成樹是指某乙個節點的度限制為k的最小生成樹。具體的做法去看 或者黑書吧,這裡不詳細講了。理解最小度限制生成樹的解法,最主要的就是看懂如何由m度生成樹求m 1度生成樹,另外要理解無解的情況。今天終於把模板整理出來了,prim那裡用了優先佇列優化,新增刪除邊破環那裡用的是動態規劃。試了試pk...