【bzoj1517】Met

  • 本文为博主原创,未经许可不得转载

上午被子祯的题虐了一通,下午便去做一发水题。

想知道我是怎么选中这道题的?写一个随机数生成器就行了。。。。。。

这是一道结论题。

首先我们按照拓扑序将图分层,对于一个点,我们都可以从它的子树中选出一个点使得这个点被覆盖。

考虑每一层,我们最多可以选$2l$个点,由于每层的节点数必然是单调递增的,所以假设在第i层选了x个点,那么i-1层一定可以选$min(x,cnt[i-1])$个点

所以我们只需要拓扑排序统计每层的节点数即可

结论就是$ans=\sum min(cnt[i],l*2)$ (cnt[i]表示第i层节点数)

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
#include<bits/stdc++.h>
#define FILE "read"
#define MAXN 1000010
using namespace std;
struct node{int y,next;}e[MAXN<<1];
int n,m,len,ans,Link[MAXN],d[MAXN],q[MAXN],cnt[MAXN],level[MAXN];
char buf[1<<15],*fs,*ft;
inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline int read(){
int x=0,f=1; char ch=getc();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getc();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getc();}
return x*f;
}
void insert(int x,int y){e[++len].next=Link[x];Link[x]=len;e[len].y=y;d[y]++;}
void topsort(){
int head=0,tail=0;
for(int i=1;i<=n;++i) if(d[i]==1) q[++tail]=i;
while(++head<=tail){
for(int i=Link[q[head]];i;i=e[i].next){
if(--d[e[i].y]==1){
q[++tail]=e[i].y;
level[q[tail]]=level[q[head]]+1;
}
}
}
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
n=read(); m=read();
for(int i=1;i<n;++i){
int x=read(),y=read();
insert(x,y); insert(y,x);
}
topsort();
for(int i=1;i<=n;++i) cnt[level[i]]++;
for(int i=0;cnt[i];++i) ans+=min(m*2,cnt[i]);
printf("%d\n",ans);
return 0;
}
文章目录
,