BZOJ NOI十连测 第二测 T1
2016-06-16 14:56
169 查看
![](https://images2015.cnblogs.com/blog/911287/201606/911287-20160616144509229-589295918.png)
![](https://images2015.cnblogs.com/blog/911287/201606/911287-20160616144522104-1822622512.png)
![](https://images2015.cnblogs.com/blog/911287/201606/911287-20160616144530885-1403659413.png)
出题人居然是个哲学家。。
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); }
相关文章推荐
- AD采样的一个例子
- dotnetbar入门
- 网络信息安全学习平台---脚本关第14题
- C++中的RAII用法
- 我的第一篇博客
- jxl自动设置列宽
- VTK入门(三)--图像加工处理(一)
- Java NIO
- 怎样保持一个良好的开发状态
- 掌握Tiles 框架 (一)---Tiles入门和Tiles 框架和体系结构
- 《软件工程》课程总结
- struts2环境配置
- Python 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)
- linux进程调度函数浅析
- 快速排序算法-
- EventBus 3.0新版使用说明(及其使用方法)
- 浅析Python中else语句块的使用技巧
- Python的垃圾回收机制
- 基于SDP的提议/应答(offer/answer)模型简介
- 【JavaScript笔记三】你也有控制权(DOM操作)