JZOJ 4.1 C组 【NOIP动态规划专题】电子眼
Description
中山市石一个环境优美、气候宜人的小城市。因为城市的交通并不繁忙,市内的道路网很稀疏。准确地说,中山市有N条马路和N个路口,每条马路连接两个路口,每两个路口之间最多只有一条马路。作为一条交通网络,显然每两个路口之间都是可达的。为了更好地管理中山市的交通,市长决定在一些路口加装电子眼,用来随时监视路面情况。这些装在路口的电子眼能够监视所有连接到这个路口的马路。现在市长想知道最少需要在多少个路口安装电子眼才能监视所有的马路。市长已经把所有的路口都编上了1~N的号码。 给你中山市的地图,你能帮忙吗?
Input
输入文件第1行包括一个数字N(1<=N<=100000),表示中山市的路口数。接下来N行,第i+1行的第一个数字ki表示有ki条马路与路口i相连,后面紧跟着ki个数字,表示与路口i直接相连的路口。
Output
输出最少需要安装电子眼的数量。
Sample Input
3
2 2 3
2 1 3
2 1 2
Sample Output
2
Data Constraint
1<=N<=100000
其实这是一个类似于树的无向图
设f[i,0/1]为这条路装和不装的两种情况。
如果这条边不装的话,要将所有的路都能监视到的话,他的子节点或者父节点都要放。
如果这条边装的话,他的父子节点都不用装。
那么从任意一个点出发,要找到每个点装和不装所要用的电子眼的个数,就要用递归实现。
代码如下:
uses math;
var
a:array[1..200000] of longint;
w,b:array[1..100001] of longint;
x:array[1..100001] of boolean;
f:array[1..100000,0..1] of longint;
n,m,i,j,k,l:longint;
function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end;
procedure dp(t:longint);
var
i,s1,s2:longint;
begin
s1:=1;
s2:=0;
for i:=w[t] to w[t+1]-1 do
begin
if x[a[i]]=false then
begin
x[a[i]]:=true;
dp(a[i]);
s1:=s1+min(f[a[i],0],f[a[i],1]);
end;
s2:=s2+f[a[i],1];
end;
f[t,1]:=s1;
f[t,0]:=s2;
end;
begin
readln(n);
for i:=1 to n do
begin
read(b[i]);
w[i]:=m+1;
for j:=m+1 to m+b[i] do read(a[j]);
m:=m+b[i];
end;
w[n+1]:=m+1;
x[1]:=true;
dp(1);
writeln(min(f[1,0],f[1,1]));
end.