电子眼
Description
中山市石一个环境优美、气候宜人的小城市。因为城市的交通并不繁忙,市内的道路网很稀疏。准确地说,中山市有N-1条马路和N个路口,每条马路连接两个路口,每两个路口之间最多只有一条马路。作为一条交通网络,显然每两个路口之间都是可达的。为了更好地管理中山市的交通,市长决定在一些路口加装电子眼,用来随时监视路面情况。这些装在路口的电子眼能够监视所有连接到这个路口的马路。现在市长想知道最少需要在多少个路口安装电子眼才能监视所有的马路。市长已经把所有的路口都编上了1~N的号码。
给你中山市的地图,你能帮忙吗?
Input
输入文件traffic.in的第1行包括一个数字N(1<=N<=100000),表示中山市的路口数。接下来N-1行,每行两个数字x_i和y_i,用来描述N-1条路所连接的两个路口的编号。
Output
输出最少需要安装电子眼的数量。
Sample Input
3
1 2
1 3
Sample Output
1
Hint
数据规模:
30% N<=100
50% N<=1000
100% N<=100000
解题思路
这道题其实和没有上司的舞会这道题的思路是差不多的,只不过这道题不用考虑上司与下属不能同时出现的问题,并且初值不用输入。
动态转移方程:
i f ( b [ a [ i ] . y ] = = 1 ) if(b[a[i].y]==1) if(b[a[i].y]==1)
c o n t i n u e ; continue; continue;
b [ a [ i ] . y ] = 1 ; b[a[i].y]=1; b[a[i].y]=1;
d p ( a [ i ] . y ) ; dp(a[i].y); dp(a[i].y);
f [ d e p ] [ 0 ] = f [ d e p ] [ 0 ] + f [ a [ i ] . y ] [ 1 ] ; f[dep][0]=f[dep][0]+f[a[i].y][1]; f[dep][0]=f[dep][0]+f[a[i].y][1];
f [ d e p ] [ 1 ] = m i n ( f [ a [ i ] . y ] [ 0 ] , f [ a [ i ] . y ] [ 1 ] ) + f [ d e p ] [ 1 ] ; f[dep][1]=min(f[a[i].y][0],f[a[i].y][1])+f[dep][1]; f[dep][1]=min(f[a[i].y][0],f[a[i].y][1])+f[dep][1];
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long long n,x1,y1,t,h[200001],f[200001][2],b[200001];
struct node
{
long long x,y,next;
}a[200001];
void ljb(int x,int y)
{
t++;
a[t].x=x;
a[t].y=y;
a[t].next=h[x];
h[x]=t;
}
void dp(int dep)
{
f[dep][1]=1;//赋初值
f[dep][0]=0;
b[dep]=1;
for(int i=h[dep];i;i=a[i].next)
{
if(b[a[i].y]==1)
continue;
b[a[i].y]=1;
dp(a[i].y);
f[dep][0]=f[dep][0]+f[a[i].y][1];
f[dep][1]=min(f[a[i].y][0],f[a[i].y][1])+f[dep][1];//动态转移方程
}
}
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n-1;i++)
{
scanf("%lld%lld",&x1,&y1);
ljb(x1,y1);
ljb(y1,x1);
}
dp(1);
printf("%d",min(f[1][0],f[1][1]));//找出最小值
}