题意
有一座古城堡,里面的路形成一棵树, 某个士兵在一个节点上时,与该节点相连的所有边都将能被瞭望到。问最少需要多少士兵才可以使所有的路都被瞭望到。 输入数据表示一棵树,描述如下。 第一行一个数 $N$ ,表示树中节点的数目。 第二到第 $N+1$ 行,每行描述每个节点信息,依次为该节点编号 $i$,数值 $k$,$k$ 表示后面有 $k$ 条边与节点 $i$ 相连,接下来 $k$ 个数,分别是每条边的所连节点编号 $r_1,r_2,\cdots ,r_k$。 对于一个有 $N$ 个节点的树,节点标号在 $0$ 到 $N-1$ 之间,且在输入文件中每条边仅出现一次。
思路
设$f[x][0]$表示第$i$个节点不放士兵,以$x$节点为根节点的子树所需要士兵的最少数量。 设$f[x][1]$表示第$i$个节点放士兵,以$x$节点为根节点的子树所需要士兵的最少数量。 那么有: $$f[x][0]=\sum{f[y][1],y∈x的儿子}$$ $$f[x][1]=1+\sum{min(f[y][0],f[y][1]),y∈x的儿子}$$ 那么这个问题就愉快的解决了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| #include<algorithm> #include<bitset> #include<complex> #include<deque> #include<exception> #include<fstream> #include<functional> #include<iomanip> #include<ios> #include<iosfwd> #include<iostream> #include<istream> #include<iterator> #include<limits> #include<list> #include<locale> #include<map> #include<memory> #include<new> #include<numeric> #include<ostream> #include<queue> #include<set> #include<sstream> #include<stack> #include<stdexcept> #include<streambuf> #include<string> #include<typeinfo> #include<utility> #include<valarray> #include<vector> #include<cctype> #include<cerrno> #include<cfloat> #include<ciso646> #include<climits> #include<clocale> #include<cmath> #include<csetjmp> #include<csignal> #include<cstdarg> #include<cstddef> #include<cstdio> #include<cstdlib> #include<cstring> #include<ctime> using namespace std; inline int read(){ int res=0,f=1;char ch=getchar(); while(ch<'0'ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') res=res*10+ch-'0',ch=getchar(); return res*f; } inline void write(int x){ if(x<0) putchar('-'),x=-x; if(x<10) putchar(x+'0'); else{ write(x/10); putchar(x%10+'0'); } }
int n,root=0,r[1600],f[1600][3]; vector<int> v[1600]; void dp(int x){ f[x][1]=1; f[x][0]=0; if(v[x].size()==0) return ; for(int i=0;i<v[x].size();i++){ dp(v[x][i]); f[x][0]+=f[v[x][i]][1]; f[x][1]+=min(f[v[x][i]][0],f[v[x][i]][1]); } } int main(){ n=read(); for(int i=1;i<=n;i++){ int vs=read(); int k=read(); while(k--){ int x=read(); v[vs].push_back(x); r[x]=1; } } for(;r[root]==1;root++) ; dp(root); write(min(f[root][0],f[root][1]));putchar('\n'); return 0; }
|