羅区P2016戦略ゲーム
説明
ボブは、コンピュータゲーム、特に戦略ゲームをプレイするのが好きです。しかし、彼は多くの場合、すぐにゲームをプレイする方法を見つけることができませんでした。今、彼は問題を抱えています。
彼は城の道は木を形成し、古代の城を確立することを望んでいます。彼は、兵士たちはすべての方法をbeholdの過去過去分詞できるように、ツリーノードの兵士の最小数に置かれます。
ノード上の兵士が、ノードに接続されているすべてのエッジが視射できる場合、ことに留意されたいです。
あなたは彼が兵士を配置する必要がある最小の計算にボブを助けるために木を与え、プログラムをコンパイルします。
入力
最初のラインN、ツリー内のノードの数。
以下のように、第2行は、各ノードの情報を記述し、各ラインで、+ N 1行に:参照ノードI、K(接続の後ろにKエッジがIノードします)。
各エッジにおいて、R1、R2、···、RKの他のノードのそれぞれ次数k、。
ツリーノードのN(0 <N <= 1500)のために、0とn-1との間のノード番号は、一度だけ入力データ内のすべてのエッジが現れます。
出力
- 出力ファイルは、兵士の最小数をを求めているだけの数が含まれています。
サンプル入力
4 0 1 1 1 2 2 3 2 0 3 0
サンプル出力
1
ソリューション:
以下からの抜粋pengym大幅に
実際には、いくつかの方法があり、この質問、より明白なのおそらく1 木のDPバーは、階下の大物の多くは、すでにここに(、そこに説明されています
)再びそれを言わないでください、この質問をよく見は典型的に見つけることができる最低限のポイントカバレッジ。最小頂点被覆は1つの図に示し:ポイントを
側は、それに取り付けられたカバー最小カバレッジのポイントを見つけることができます。これはまさに尋ねた同じ質問です。ならびに定理、最小頂点カバー=
マッチの最大数。それは無向グラフ/ 2であるならば。したがって、ハンガリーのアルゴリズムを演奏を考えるのは簡単です。
#include <iostream>
#include <cstdio>
#include <cstring>
#define N 1505
using namespace std;
struct E {int next, to;} e[N * N * 2];
int n, num, ans;
int h[N], mat[N];
bool vis[N];
int read()
{
int x = 0; char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return x;
}
void add(int u, int v)
{
e[++num].next = h[u];
e[num].to = v;
h[u] = num;
}
bool dfs(int x)
{
for(int i = h[x]; i != 0; i = e[i].next)
if(!vis[e[i].to])
{
vis[e[i].to] = 1;
if(!mat[e[i].to] || dfs(mat[e[i].to]))
{
mat[e[i].to] = x;
return 1;
}
}
return 0;
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
int u = read() + 1, k = read();
for(int i = 1; i <= k; i++)
{
int v = read() + 1;
add(u, v), add(v, u);
}
}
for(int i = 1; i <= n; i++)
{
memset(vis, 0, sizeof(vis));
if(dfs(i)) ans++;
}
cout << ans / 2;
return 0;
}