POJ 1463 淺談簡單樹形動態規劃及樹上最小點覆蓋
世界真的很大
很多經典的圖論問題放在樹上就顯得簡單
二分圖的最小點覆蓋
這裡就變成了一個簡單的樹形DP而已
看題先:
description:
鮑勃喜歡玩電腦遊戲,特別是戰略遊戲,但有時候他無法快速找到解決方案,那麼他很傷心。 現在他有以下問題。 他必須捍衛一座中世紀城市,其道路形成一棵樹。 他必須將最少數量的士兵放在節點上,以便他們可以觀察所有的邊緣。 你可以幫助他嗎?
您的程式應該找到Bob為給定樹提供的最小兵數。
例如樹:
input:
The input contains several data sets in text format. Each data set represents a tree with the following description:
the number of nodes
the description of each node in the following format
node_identifier:(number_of_roads) node_identifier1 node_identifier2 … node_identifiernumber_of_roads
or
node_identifier:(0)The node identifiers are integer numbers between 0 and n-1, for n nodes (0 < n <= 1500);the number_of_roads in each line of input will no more than 10. Every edge appears only once in the input data.
output:
The output should be printed on the standard output. For each given input data set, print one integer number in a single line that gives the result (the minimum number of soldiers). An example is given in the following:
簡單樹形DP,大概是用來練手的吧
樹形DP與子樹有關,考慮一個點的狀態只有選或者不選,所以設計狀態01表示這個點選不選
考慮狀態轉移及子樹狀態合併,如果這個點選了那他的所有子樹都是可選可不選,sigma min(f(v,0),f(v,1))
如果這個點不選,那麼其所有子樹都必須選,sigma f(v,1)
但是這道題的讀入真的是噁心
不妨礙1A
233
完整程式碼:
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace std;
struct edge
{
int v,last;
}ed[100010];
int n,num=0;
int head[100010],f[100010][2];
void init()
{
num=0;
memset(head,0,sizeof(head));
memset(f,0,sizeof(f));
}
void add(int u,int v)
{
num++;
ed[num].v=v;
ed[num].last=head[u];
head[u]=num;
}
void dfs(int u,int fa)
{
f[u][1]=1;
for(int i=head[u];i;i=ed[i].last)
{
int v=ed[i].v;
if(v==fa) continue ;
dfs(v,u);
f[u][1]+=min(f[v][0],f[v][1]);
f[u][0]+=f[v][1];
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
init();
for(int i=1;i<=n;i++)
{
int u,w;
scanf("%d:(%d)",&u,&w);
while(w--)
{
int v;
scanf("%d",&v);
add(u,v),add(v,u);
}
}
dfs(1,1);
printf("%d\n",min(f[1][0],f[1][1]));
}
return 0;
}
/*
Whoso pulleth out this sword from this stone and anvil is duly born King of all England
*/
嗯,就是這樣