SPOJ 1479 +SPOJ 666 無向樹最小點覆蓋 ,第二題要方案數,樹形dp
題意:求一顆無向樹的最小點覆蓋。
本來一看是最小點覆蓋,直接一下敲了二分圖求最小割,TLE。
樹形DP,叫的這麼玄乎,本來是線性DP是線上往前\後推,而樹形DP就是在樹上,由葉子結點狀態向根狀態推。
dp[u][1/0]:表示,結點u,1:選擇,0,:不選。dp值是以改點為根(目前為止,dfs遍歷順序自然決定了樹的層)的已經選擇點數,自然開始時不知道,對每個點,初值dp[u][0]=0、
dp[u][1]=1,回溯的時候:
1:dp[u][1]+=min(dp[v][1],dp[v][0]);該節點選擇了,那麼子節點可選可不選。
2:dp[u][0]+=dp[v][1];該節點沒有選擇,則其子節點必需選擇。
#include<iostream> #include<queue> #include<stack> #include<cstdio> #include<vector> using namespace std; int n; vector<vector<int> >v(100010); int vis[100010]; int dp[100010][2]; inline int minn(int a,int b) { if(a<b)return a; return b; } void dfs(int u) { dp[u][0]=0; //不放,0個 dp[u][1]=1; //放一個, for(int i=0;i<v[u].size();i++) { int vv=v[u][i]; if(!vis[vv]) { vis[vv]=1; dfs(vv); dp[u][0]+=dp[vv][1]; //回溯時加上 dp[u][1]+=minn(dp[vv][1],dp[vv][0]); } } } int main() { scanf("%d",&n); int tx,ty; for(int i=0;i<n-1;i++) { scanf("%d%d",&tx,&ty); v[tx].push_back(ty); v[ty].push_back(tx); } vis[1]=1; dfs(1); cout<<minn(dp[1][0],dp[1][1]); //結果為根放與不放的狀態最小值 return 0; }
666,求最優時候方案數,
多一個DP方程即可。
#include<iostream> #include<cstdio> #include<vector> using namespace std; int n; vector<vector<int> >v(100020); int vis[100020]; struct state { int light; int count; }; state dp[100020][2]; inline int minn(int a,int b) { if(a<b)return a; return b; } void dfs(int u) { dp[u][0].light=0; //不放,0個 dp[u][1].light=1; //放一個, dp[u][0].count=dp[u][1].count=1; for(int i=0;i<v[u].size();i++) { int vv=v[u][i]; if(!vis[vv]) { vis[vv]=1; dfs(vv); dp[u][0].light+=dp[vv][1].light; //回溯時加上 dp[u][1].light+=minn(dp[vv][1].light,dp[vv][0].light); dp[u][0].count= dp[u][0].count*dp[vv][1].count%10007; if(dp[vv][1].light<dp[vv][0].light) dp[u][1].count=dp[u][1].count*dp[vv][1].count%10007; else if (dp[vv][1].light>dp[vv][0].light) dp[u][1].count=dp[u][1].count*dp[vv][0].count%10007; else dp[u][1].count=dp[u][1].count*(dp[vv][0].count+dp[vv][1].count)%10007; } } } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d",&n); int tx,ty; for(int i=0;i<=n;i++) { v[i].clear();vis[i]=0; } for(int i=0;i<n-1;i++) { scanf("%d%d",&tx,&ty); v[tx].push_back(ty); v[ty].push_back(tx); } vis[1]=1; dfs(1); int ans1=minn(dp[1][0].light,dp[1][1].light); //結果為根放與不放的狀態最小值 if(dp[1][0].light<dp[1][1].light) { printf("%d %d\n",ans1,dp[1][0].count); } else if(dp[1][0].light>dp[1][1].light) { printf("%d %d\n",ans1,dp[1][1].count); } else { int ans2= (dp[1][0].count%10007+dp[1][1].count%10007)%10007; printf("%d %d\n",ans1,ans2); } } return 0; }
相關推薦
SPOJ 1479 +SPOJ 666 無向樹最小點覆蓋 ,第二題要方案數,樹形dp
題意:求一顆無向樹的最小點覆蓋。 本來一看是最小點覆蓋,直接一下敲了二分圖求最小割,TLE。 樹形DP,叫的這麼玄乎,本來是線性DP是線上往前\後推,而樹形DP就是在樹上,由葉子結點狀態向根狀態推。 dp[u][1/0]:表示,結點u,1:選擇,0
【CodeChef】Annual Parade -最小費用最大流&無向圖最小鏈覆蓋
傳送門:Annual Parade 題解 求鏈覆蓋所有點的最小花費,考慮拆點跑最小費用最大流。 1 0
無向圖最小點割集解法
from: http://www.cppblog.com/imky/archive/2010/08/14/123414.html 無向圖最小點割集,確定起點S,終點T。每個點都有自己的點權值vi,求最小點權和的割點集,使得S無法到達T。 解法:將每個點拆分為兩個點v和v',
hdu6311(無向圖最小路徑覆蓋->尤拉路徑->fleury 尤拉路徑模板)
這題主要是個套路。。就是求無向圖最小路徑覆蓋。。 與有向圖的二分圖做法不同,這個是轉化為求最少的尤拉路徑。。 尤拉圖有個結論是尤拉路徑的個數為度為奇數的點的個數/2(可以類比歐拉回路的結論) 然後求尤拉路徑的方法是fleury演算法。。其思想就是暴力dfs,然後巧妙的地
[HDOJ6081] 度度熊的王國戰略(無向圖最小割,數據水)
eof printf ret pri sin %d logs ems ++ 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6081 無向圖求割點,應該是個論文題,16年有一篇SW算法+斐波那契堆優化的論文。 但是這數據怎麽這!
poj1966Cable TV Network——無向圖最小割(最大流)
一個 can struct div ret memcpy AI ostream () 題目:http://poj.org/problem?id=1966 把一個點拆成入點和出點,之間連一條邊權為1的邊,跑最大流即最小割; 原始的邊權賦成inf防割; 枚舉源點和匯點,直接相鄰
藍書(演算法競賽進階指南)刷題記錄——POJ1734 Sightseeing trip(無向圖最小環)
題目:poj1734. 題目大意:給定一張無向圖,求這張無向圖邊權和最小的節點大於3個的環,若有解輸出任意一個方案,否則輸出“No solution.”. 這就是一個較為簡單的floyd應用. 我們可以先把floyd模板寫下來看看floyd有什麼特殊的性質: void floyd
poj1734 無向圖最小環
要求對floyd演算法有一定的理解。 有一個神奇的地方:路徑是邊做邊更新的,防止了出現重複的點。(在不同的k時更新的路徑,中間點g[i][j]是會變化的) #include<bits/stdc++.h> using namespace std; #define
HDU 3435 無向環最小權值覆蓋
An undirected graph is a graph in which the nodes are connected by undirected arcs. An undirected arc is an edge that has no arrow. Both e
12.3日+佛洛依德處理無向圖最小環+dijkstra處理有向圖最小環
昨天的資料庫考試,題目本身都簡單的,但是感覺時間有點緊張,可能和自己有點墨跡有關。題目不怕不會做,就怕讀錯題,上了大學養成了考試“做完一遍要檢查的壞習慣”,這次沒時間檢查,所以有種做的不好的感覺。 弗洛伊德演算法是運用的動態規劃的思
HDU-1599-find the mincost route【最短路】【無向圖最小環】
find the mincost route Time Limit: 1000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4341
【USACO4.1.3】籬笆迴路 無向圖最小環
題目意思就是讓你求無向圖最小環,但是給資料的方式非常噁心。 我的用並查集+暴力的方式…… 先給每個邊的頂點標號,然後…… 把A能到B,B也能到A的邊的點,給併為一個點…… 然後floyd求最小環。 floyd最小環我自己還不是非常理解…… 但是先用著,上課再想
【杭電oj1599】find the mincost route無向圖最小環
find the mincost route Time Limit: 1000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s
floyd求無向圖最小環——poj1734
給定一個無向圖,求出圖中由 3個及以上個點構成的環的邊權和 中的最小值。(一個點不能遍歷多次)在floyd時,先迴圈k,然後是i和j,你會發現在每次進入一個新的k迴圈時,每一個d(i,j)都儲存著從i到j,只經歷了編號不超過k-1的節點的最短路、於是,min{d(i,j)+
poj 2914 無向圖最小割
最小割集◎Stoer-Wagner演算法 一個無向連通網路,去掉一個邊集可以使其變成兩個連通分量則這個邊集就是割集;最小割集當然就權和最小的割集。 可以用最小切割最大流定理: 1.min=MAXINT,確定一個源點 2.列舉匯點 3.計算最大流,並確定當前源匯的最小割集,若比
求無向圖最小割
先解釋下名詞的意思。 無向圖的割:就是去掉一些邊,使得原圖不連通,最小割就是要去掉邊的數量最小。 解決這個問題的常用辦法就是Stoer-Wagner 演算法; 先說下這個演算法的步驟後面給出證明: 1.min=MAXINT,固定一個頂點P 2.從點P用類似prim的
求樹的最大獨立集,最小點覆蓋,最小支配集 貪心and樹形dp
www 子節點 最大獨立集 com 倒序 最小支配集 交流 屬於 else 目錄 求樹的最大獨立集,最小點覆蓋,最小支配集 三個定義 貪心解法 樹形DP解法 (有任何問題歡迎留言或私聊&&歡迎交流討論哦 求樹的最大獨立集,最小點覆蓋,最小支配集 三個
樹的最小支配集、最小點覆蓋、最大獨立集 (貪心orDP)
樹的最小支配集:點集中取出儘量少的點,使剩下的點與取出來的點都有邊相連。 樹的最小點覆蓋:點集中取出儘量少的點,使得所有邊都與選出的點相連。 樹的最大獨立集:點集中取出儘量多的點,使得這些點兩兩之間沒有
樹的最小支配集、最小點覆蓋、最大獨立集【模板】
最小支配集:指從所有頂點中取儘量少的點組成一個集合,使得剩下的所有點都與取出來的點有邊相連。頂點個數最小的支配集被稱為最小支配集。這裡用貪心法來求。 1.以1號點深度優先搜尋整棵樹,求出每個點在DFS中的編號和每個點的父親節點編號。 2.按DFS的反向序列檢
樹的最小支配集,最小點覆蓋與最大獨立集
首先看一下三者的定義: 定義1 對於圖G=(V,E)來說, 最小支配集 指的是從V中取儘量少的點組成一個集合,使得對於V中剩餘的點都與取出來的點有邊相連。也就是說,設V‘是圖G的一個支配集,則對於