您的位置:首页 > 其它

BZOJ NOI十连测 第二测 T1

2016-06-16 14:56 169 查看






出题人居然是个哲学家。。

26%的程序,太SB了。。。本来我的想法也是二分+贪心,但是贪心是个怪怪的SX贪心。。

#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<time.h>
#define inf 0x7fffffff
struct edge{
int u,v,id;
}e[400005];
int tot,go[400005],first[200005],next[400005];
int Tot,Go[400005],First[200005],Next[400005];
int c[200005],b[200005],son[200005],ans,vis[200005],pd;
int pass[400005],op[400005],C[400005],Cnt,block,sum,B[200005];
int id1,id2;
int n,k;
int read(){
char ch=getchar();int t=0,f=1;
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
return t*f;
}
void Dfs(int x,int fa){
if (vis[x]) return;
c[x]=b[x];son[x]=1;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
if (pass[i]) continue;
Dfs(pur,x);
son[x]+=son[pur];
c[x]+=c[pur];
}
if (c[x]&&(n-c[x]>0)) ans=std::min(ans,std::max(son[x],n-son[x]));
}
void sbpianfen(){
ans=inf;
Dfs(1,0);
printf("%d\n",ans);
}
void insert(int x,int y){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
pass[tot]=1;
}
void add(int x,int y){
insert(x,y);op[tot]=tot+1;insert(y,x);op[tot]=tot-1;
}
void Insert(int x,int y){
Tot++;
Go[Tot]=y;
Next[Tot]=First[x];
First[x]=Tot;
}
void Add(int x,int y){
Insert(x,y);Insert(y,x);
}
int bfs(int x){
int h=1,t=1;
bool ck=0;
c[1]=x;vis[x]=1;if (b[x]) ck=1;
while (h<=t){
int now=c[h++];
for (int i=First[now];i;i=Next[i]){
int pur=Go[i];
if (vis[pur]) continue;
c[++t]=pur;
vis[pur]=1;
if (b[pur]) ck=1;
}
}
if (!ck) pd=1;
return t;
}
void dFs(int x){
if (x==n){
pd=0;
int bl=0;
for (int i=1;i<=n;i++)
First[i]=0;
Tot=0;
for (int i=1;i<n;i++)
if (!e[i].id) Add(e[i].u,e[i].v);
for (int i=1;i<=n;i++)
vis[i]=0;
for (int i=1;i<=n;i++)
if (!vis[i])
bl=std::max(bl,bfs(i));
if (pd==0) ans=std::min(ans,bl);
return;
}
e[x].id=1;
dFs(x+1);
e[x].id=0;
dFs(x+1);
}
void sxpianfen(){
for (int i=1;i<n;i++) e[i].id=0;
dFs(1);
}
void clear(int x){
int h=1,t=1;
C[1]=x;
bool ppp=1;
if (b[x]) Cnt++,ppp=0;
vis[x]=1;b[x]=0;
while (h<=t){
int now=C[h++];
for (int i=first[now];i;i=next[i]){
int pur=go[i];
if (pass[i]) continue;
if (vis[pur]) continue;
C[++t]=pur;
vis[pur]=1;
if (b[pur]) Cnt++,ppp=0;
b[pur]=0;
}
}
if (ppp) {
pd=1;
return;
}
if (t>block) pd=1;
sum-=t;
}
void work(int x,int mid,int fa,int Edge){
if (c[x]==1&&b[fa]==1&&son[x]<=block) {
pass[Edge]=1;
pass[op[Edge]]=1;
clear(x);
id1=x;id2=fa;
if (pd) return;
return;
}
else
if (k-Cnt-c[x]==1&&b[x]==1&&sum-son[x]<=block){
pass[Edge]=1;
pass[op[Edge]]=1;
clear(fa);
id1=x;id2=fa;
if (pd) return;
return;
}
else
if (c[x]==1&&son[x]<=block&&son[fa]>=block){
pass[Edge]=1;
pass[op[Edge]]=1;
clear(x);
id1=x;id2=fa;
if (pd) return;
return;
}else
if (k-Cnt-c[x]==1&&sum-son[x]==block){
pass[Edge]=1;
pass[op[Edge]]=1;
clear(fa);
id1=x;id2=fa;
if (pd) return;
return;
}
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
if (vis[pur]) continue;
if (pass[i]) continue;
work(pur,mid,x,i);
}
}
bool check(int mid){
for (int i=1;i<n;i++) std::swap(e[rand()%(n-1)+1],e[rand()%(n-1)+1]);
for (int i=1;i<=n;i++) first[i]=0;
tot=0;
for (int i=1;i<n;i++)
add(e[i].u,e[i].v);
block=mid;pd=0;
for (int i=1;i<=tot;i++)
pass[i]=0;
for (int i=1;i<=n;i++)
b[i]=B[i],vis[i]=0;
id1=1;id2=0;vis[0]=1;
sum=n;Cnt=0;
for (int i=1;i<=k;i++){
if (vis[id1]&&vis[id2]) break;
if (k-Cnt==1) break;
if (!vis[id1]){
Dfs(id1,0);
work(id1,mid,0,0);
}else{
Dfs(id2,0);
work(id2,mid,0,0);
}
if (pd) return 0;
}
for (int i=1;i<=n;i++)
if (!vis[i]) clear(i);
if (pd) return 0;
return 1;
}
void solve(){
int l=n/k,r=n,Ans=n;
while (l<=r){
int mid=(l+r)/2;
if (check(mid)) r=mid-1,Ans=mid;
else l=mid+1;
}
printf("%d\n",Ans);
}
void solve2(){
int l=n/k,r=n,Ans=n;
while (l<=r){
int mid=(l+r)/2;
if (check(mid)) r=mid-1,Ans=mid;
else l=mid+1;
}
int Tn=Ans;
l=n/k,r=n,Ans=n;
while (l<=r){
int mid=(l+r)/2;
if (check(mid)) r=mid-1,Ans=mid;
else l=mid+1;
}
Tn=std::min(Tn,Ans);
printf("%d\n",Tn);
}
int main(){
//♂
freopen("deep.in","r",stdin);
freopen("deep.out","w",stdout);
srand(time(NULL));
ans=inf;
n=read();k=read();
for (int i=1;i<n;i++){
int x=read(),y=read();
add(x,y);
e[i].u=x;e[i].v=y;
}
for (int i=1;i<=k;i++){
int x=read();
b[x]=1;B[x]=1;
}
if (n<=20) {sxpianfen();printf("%d\n",ans);return 0;}
if (k==1) {printf("%d\n",n);return 0;}
if (k==2) {sbpianfen();return 0;}
if (n<=2000) {solve();return 0;}
if (k==3) {solve2();return 0;}
if (k==n) {printf("%d\n",1);return 0;}
if (k==n-1) {printf("%d\n",2);return 0;}
solve();
}


AC程序不知道短到哪里去了

#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#define N 200005
int tot,go[N*2],next[N*2],first
;
int n,k,b
,fa
,mx
,sum
,vis
,c
;
int read(){
char ch=getchar();int t=0,f=1;
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
return t*f;
}
void insert(int x,int y){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
}
void add(int x,int y){
insert(x,y);insert(y,x);
}
void bfs(){
int h=1,t=1;for (int i=1;i<=n;i++) vis[i]=0;
c[1]=1;
vis[1]=1;
while (h<=t){
int now=c[h++];
for (int i=first[now];i;i=next[i]){
int pur=go[i];
if (vis[pur]) continue;
vis[pur]=1;
c[++t]=pur;
fa[pur]=now;
}
}
}
bool check(int mid){
int f;
memset(sum,0,sizeof sum);
memset(mx,0,sizeof mx);
for (int i=n;i>=1;i--){
int u=c[i];
if (b[u]) mx[u]=mid-1;
else sum[u]++;
f=(mx[u]>=sum[u])?mx[u]-sum[u]:-sum[u];
if (u==1&&f<0) return 0;
if (f<0) sum[fa[u]]-=f;
else mx[fa[u]]=std::max(mx[fa[u]],f);
}
return 1;
}
int main(){
n=read();k=read();
for (int i=1;i<n;i++){
int x=read(),y=read();
add(x,y);
}
for (int i=1;i<=k;i++){
int x=read();
b[x]=1;
}
bfs();
int l=n/k,r=n,ans;
while (l<=r){
int mid=(l+r)>>1;
if (check(mid)) r=mid-1,ans=mid;
else l=mid+1;
}
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: