題目連結:http://acm.hust.edu.cn:8080/judge/problem/viewProblem.action?id=22719
題目大意:一棵n(1~10,000)個結點的樹,在某一點上放置一個網絡裝置,信号可以覆寫該結點及其相鄰的結點,求至少要放置多少個結點,信号能覆寫整棵樹.
思路:容易知道連接配接樹葉的結點一定要放置裝置,是以先把連接配接樹葉的結點都放了裝置,并把這些結點起來标記(相當于去掉),然後再回溯處理.也就是對樹暴力深搜.
代碼:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
//#define ull unsigned __int64
//#define ll __int64
#define ull unsigned long long
#define ll long long
#define son1 New(p.xl,xm,p.yl,ym),(rt<<2)-2
#define son2 New(p.xl,xm,min(ym+1,p.yr),p.yr),(rt<<2)-1
#define son3 New(min(xm+1,p.xr),p.xr,p.yl,ym),rt<<2
#define son4 New(min(xm+1,p.xr),p.xr,min(ym+1,p.yr),p.yr),rt<<2|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define middle (l+r)>>1
#define MOD 1000000007
#define esp (1e-8)
const int INF=0x3F3F3F3F;
const double DINF=10000.00;
//const double pi=acos(-1.0);
const int N=10010;
int n,m,tot;
vector<int>vct[N];
int flag[N],cov[N];
struct node{
int fa,p;
};
void init(){
int i,x,y;
for(i=1;i<=n;i++) vct[i].clear();
for(i=1;i<n;i++){
scanf("%d%d",&x,&y);
vct[x].push_back(y);
vct[y].push_back(x);
}
memset(flag,0,sizeof(flag));
memset(cov,0,sizeof(cov));
tot=0;
}
void dfs(int rt,int fa){
if(vct[rt].size()==1) return;
int i,j,size=vct[rt].size();
int ok1=0,ok2=0;
for(i=0;i<size;i++) if(vct[rt][i]!=fa){
dfs(vct[rt][i],rt);
if(flag[vct[rt][i]]) ok1=1;
if(!cov[vct[rt][i]]) ok2=1;
}
if(ok2) flag[rt]=cov[rt]=1;
else if(ok1) cov[rt]=1;
}
void sof(){
vct[1].push_back(0);
vct[0].push_back(1);
vct[0].push_back(0);
dfs(0,0);
for(int i=0;i<=n;i++) if(flag[i]) tot++;
//for(int i=1;i<=n;i++){if(flag[i]) printf("%d ",i);}puts("");
printf("%d\n",tot);
}
int main(){
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
//int T,cas;scanf("%d",&T);for(cas=1;cas<=T;cas++){
while(~scanf("%d",&n)){
init(),sof();
}
return 0;
}