Description
八中有N个房间和N-1双向通道,任意两个房间均可到达.现在出了一件极BT的事,就是八中开始闹鬼了。老大决定加强安保,现在如果在某个房间中放一个士兵,则这个房间以及所有与这个房间相连的房间都会被控制.现在
老大想知道至少要多少士兵可以控制所有房间.以及有多少种不同的方案数.
Input
第一行一个数字N,代表有N个房间,房间编号从1开始到N.N<=500000,下面将有N-1行,每行两个数,代表这两个房间相连.
Output
第一行输出至少有多少个士兵才可以控制所有房间第二行输出有多少种方案数,方案数会比较大,输出除以1032992941的余数吧.
Sample Input
6
1 2
1 3
1 5
1 4
5 6
1 2
1 3
1 5
1 4
5 6
Sample Output
2
2
2
HINT
第一种方案是将士兵放在1号房间及6号房间
第二种方案是将士兵放在1号房间及5号房间
是的这题可以用树DP做。
0 1 2分别表示被子节点保护 自己放 不被保护
然后转移用乘法原理加法原理乱搞搞就可以了
记得分析清楚每种方法造成的方案数
以及。。我写的在bzoj上爆栈了= =大概是局部变量用太多?所以我特判了下一条链的情况【反正想卡还是随便卡】
各种手滑所以写了好久
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
struct line
{
int s,t;
int next;
}a[1000001];
int head[500001];
int edge;
inline void add(int s,int t)
{
a[edge].next=head[s];
head[s]=edge;
a[edge].s=s;
a[edge].t=t;
}
long long f[500001][3];
long long fx[500001][3];
long long mod=1032992941;
bool v[500001];
int fa[500001];
inline long long power(long long x,int y)
{
long long tx=1;
while(y!=0)
{
if(y%2==1)
tx=(tx*x)%mod;
x=(x*x)%mod;
y=y/2;
}
return tx;
}
inline void trdp1(int d)
{
v[d]=true;
fx[d][2]=1;
fx[d][1]=1;
fx[d][0]=1;
int i;
bool flag=false;
long long minx0=1,minx1=1,sx=1;
int minx=2100000000;
int st=0;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(!v[t])
{
fa[t]=d;
trdp1(t);
if(f[t][1]<=f[t][0]||f[t][0]==0)
{
f[d][0]+=f[t][1];
if(f[t][1]==f[t][0])
{
minx=min(minx,0);
fx[d][0]=(fx[d][0]*(fx[t][0]+fx[t][1]))%mod;
minx1=(minx1*(fx[t][0]+fx[t][1]))%mod;
minx0=(minx0*fx[t][0])%mod;
}
else
{
minx=-1;
fx[d][0]=(fx[d][0]*fx[t][1])%mod;
}
flag=true;
}
else
{
f[d][0]+=f[t][0];
fx[d][0]=(fx[d][0]*fx[t][0])%mod;
sx=(sx*fx[t][0])%mod;
st++;
}
f[d][1]+=min(min(f[t][0],f[t][1]),f[t][2]);
long long xtx=0;
if(f[t][1]<=f[t][2])
{
xtx+=fx[t][1];
if(f[t][1]==f[t][2])
xtx+=fx[t][2];
}
else
xtx+=fx[t][2];
fx[d][1]=(fx[d][1]*xtx)%mod;
xtx=f[t][0]>0?f[t][0]:2100000000;
if(xtx<f[t][1])
{
f[d][2]+=xtx;
fx[d][2]=(fx[d][2]*fx[t][0])%mod;
}
else if(xtx==f[t][1])
{
f[d][2]+=xtx;
fx[d][2]=(fx[d][2]*(fx[t][0]+fx[t][1]))%mod;
}
else
{
f[d][2]+=f[t][1];
fx[d][2]=(fx[d][2]*fx[t][1])%mod;
}
}
}
if(!flag&&st!=0)
{
f[d][0]++;
fx[d][0]=(fx[d][0]*power(sx,mod-2))%mod;
long long s=0;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t==fa[d])
continue;
s=(s+((sx*power(fx[t][0],mod-2))%mod)*fx[t][1]%mod)%mod;
}
fx[d][0]=(fx[d][0]*s)%mod;
}
else if(minx==0)
{
fx[d][0]=(fx[d][0]*power(minx1,mod-2))%mod;
long long xtx=minx1-minx0;
while(xtx<0)
xtx+=mod;
fx[d][0]=(fx[d][0]*xtx)%mod;
}
f[d][1]++;
}
int edg[500001];
int main()
{
freopen("lamps.in","r",stdin);
freopen("lamps.out","w",stdout);
int n;
scanf("%d",&n);
int i;
int s,t;
bool flag=true;
for(i=1;i<=n-1;i++)
{
scanf("%d%d",&s,&t);
edge++;
add(s,t);
edge++;
add(t,s);
edg[s]++;
edg[t]++;
if(edg[s]>2||edg[t]>2)
flag=false;
}
if(flag)
{
int xt=(n+1)/3;
printf("%d\n%d\n",xt,xt+1);
return 0;
}
memset(v,false,sizeof(v));
trdp1(1);
/* for(i=1;i<=n;i++)
printf("%d:%I64d %I64d %I64d\n",i,f[i][0],f[i][1],f[i][2]);
printf("\n");
for(i=1;i<=n;i++)
printf("%d:%I64d %I64d %I64d\n",i,fx[i][0],fx[i][1],fx[i][2]);*/
printf("%lld\n",min(f[1][0],f[1][1]));
if(f[1][0]==f[1][1])
printf("%lld\n",(fx[1][0]+fx[1][1])%mod);
else if(f[1][1]<f[1][0]||f[1][0]==0)
printf("%lld\n",fx[1][1]);
else if(f[1][0]<f[1][1])
printf("%lld\n",fx[1][0]);
return 0;
}