ボブは、コンピュータゲーム、特に戦略的なゲームを楽しんでいますが、時には彼は解決策が十分に速く見つけることができないし、彼は非常に悲しいです。今、彼は次のような問題があります。彼は中世の街、ツリーを形成しているの道を守る必要があります。彼は、彼らがすべてのエッジを観察できるように、ノード上の兵士の最小数を置くことがあります。あなたは彼を助けることはできますか?
あなたのプログラムは、ボブが与えられた木のために入れて持っている兵士の最小数を見つける必要があります。
入力ファイルはテキスト形式の複数のデータセットが含まれています。各データセットは、以下の説明でツリーを表す:
ノードの数
以下のフォーマット内の各ノードの説明
node_identifier:(number_of_roads)node_identifier1 node_identifier2 ... node_identifier
又は
node_identifier:(0)
ノード識別子は、N個のノードに対して、0とn-1の間の数値の整数である(0 <N <= 1500)。すべてのエッジが入力されたデータに一度だけ表示されます。
ツリーの例:
溶液(ノード1での)1人の兵士です。
出力は標準出力にプリントされなければなりません。各所与の入力データセットに対して、結果(兵士の最小数)を与える単一の行に1つの整数番号を印刷します。例は以下の表に与えられます。
Input
4
0:(1) 1
1:(2) 2 3
2:(0)
3:(0)
5
3:(3) 1 4 2
1:(1) 0
2:(0)
0:(0)
4:(0)
Output
1
2
問題の意味:点の所定数の最小エッジツリーが覆わ所要;
アイデアを:二部グラフDOの1つの最大マッチングは、最小エッジカバーの最大数と一致することであり、2ツリーDP :. Dpの[U] [ 0] Uで表されますUがとられていないツリーのルートポイントの数、DPで[U] [1] uはuが状態遷移方程式の数を取ることを指し、ツリーのルートノードとして表さ:. DP [U] [0 ] + = DP [V] [1]; DP [U] [1] + =分(DP [V] [0]、DP [V] [1])。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=1550;
int head[maxn],ip;
int dp[maxn][2],n;
struct note{
int v,next;
}edge[maxn*4];
void init(){
memset(head,-1,sizeof(head));
ip=0;
}
void addedge(int u,int v){
edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++;
}
void dfs(int u,int pre){
dp[u][1]=1;
dp[u][0]=0;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v==pre) continue;
dfs(v,u);
dp[u][0]+=dp[v][1];
dp[u][1]+=min(dp[v][0],dp[v][1]);
}
}
int main(){
while(~scanf("%d",&n)){
init();
for(int i=0;i<n;i++){
int u,k;
scanf("%d:(%d)",&u,&k);
u++;
for(int j=0;j<k;j++){
int v;
scanf("%d",&v);
v++;
addedge(u,v);
addedge(v,u);
}
}
memset(dp,0,sizeof(dp));
dfs(1,-1);
printf("%d\n",min(dp[1][0],dp[1][1]));
}
return 0;
}