Description
中山市石一个环境优美、气候宜人的小城市。因为城市的交通并不繁忙,市内的道路网很稀疏。准确地说,中山市有N条马路和N个路口,每条马路连接两个路口,每两个路口之间最多只有一条马路。作为一条交通网络,显然每两个路口之间都是可达的。为了更好地管理中山市的交通,市长决定在一些路口加装电子眼,用来随时监视路面情况。这些装在路口的电子眼能够监视所有连接到这个路口的马路。现在市长想知道最少需要在多少个路口安装电子眼才能监视所有的马路。市长已经把所有的路口都编上了1~N的号码。 给你中山市的地图,你能帮忙吗?
Input
输入文件第1行包括一个数字N(1<=N<=100000),表示中山市的路口数。接下来N行,第i+1行的第一个数字ki表示有ki条马路与路口i相连,后面紧跟着ki个数字,表示与路口i直接相连的路口。
Output
输出最少需要安装电子眼的数量。
f[i] f [ i ] 表示不选i节点时最少安装电子眼的数量
g[i] g [ i ] 表示选i节点时最少安装电子眼的数量
我们可以遍历整一棵树,在回溯的时候判断,动态转移方程为:
#include
#include
using namespace std;
struct node{
int y,next;
}a[200001];
int len,n,last[200001],f[200001],g[200001]; bool b[200001];
void dp(int k)
{
int q=1,w=0;
for (int i=last[k];i;i=a[i].next)
{
if (!b[a[i].y]) {
b[a[i].y]=1;
dp(a[i].y);
q+=min(f[a[i].y],g[a[i].y]);
}
w+=g[a[i].y];
}
g[k]=q;
f[k]=w;
}
int main()
{
scanf("%d",&n);
int x,z;
for (int i=1;i<=n;i++)
{
scanf("%d",&z);
for (int j=1;j<=z;j++)
{
scanf("%d",&x);
a[++len]={x,last[i]}; last[i]=len;
}
}
b[1]=1; dp(1);
printf("%d",min(f[1],g[1]));
}