題意: 全部邊覆蓋,所加的士兵的最小值,遞推式可直接看代碼。說起來邊覆蓋感覺好像。。二分圖?
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1600;
struct node
{
int to,next;
node(){}
node(int a,int b){to = a; next = b;}
}edge[maxn];
int h[maxn], in[maxn], out[maxn], dp[maxn][2];
int edgenum;
void init()
{
edgenum = 0;
for(int i = 0; i < maxn; i++)
h[i] = -1, in[i] = out[i] = dp[i][0] = dp[i][1] = 0;
}
void add(int f,int t)
{
edge[edgenum] = node(t,h[f]);
h[f] = edgenum++;
}
int solve(int u)
{
if(out[u] == 0)
{
dp[u][1] = 1;
return 0;
}
int ret = 0,ret1 = 0;
for(int i = h[u]; ~i; i = edge[i].next)
{
int v = edge[i].to;
solve(v);
ret += dp[v][1];
ret1 += min(dp[v][0],dp[v][1]);
}
dp[u][1] = ret1 + 1;
dp[u][0] = ret;
return 0;
}
int main()
{
int n,a,b,c;
while(~scanf("%d",&n))
{
init();
for(int i = 0; i < n ; i++)
{
scanf("%d:(%d)",&a,&b);
for(int j = 0; j < b; j++)
{
scanf("%d",&c);
add(a,c);
out[a] ++; in[c] ++;
}
}
int root = -1;
for(int i = 0; i < n; i++)
{
if(out[i] != 0 && in[i] == 0)
root = i;
}
solve(root);
printf("%d\n",min(dp[root][1],dp[root][0]));
}
return 0;
}