NOIP2017提高组模拟赛 10 (总结)
来源:互联网 发布:ipad设计软件 编辑:程序博客网 时间:2024/05/16 12:42
NOIP2017提高组模拟赛 10 (总结)
第一题 机密信息
一道简单的模拟题,暴力找S、T的lca,将路径上的点的值累加。
是S已经打开,到看到T(也就是打开了T的父亲)的路径。
注意一些特殊情况:
①S是T的祖先,或T是S的祖先。
②S和T的祖先不为S或T(需要减掉T打开的时间)。
#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define imax(a,b) ((a>b)?(a):(b))#define imin(a,b) ((a<b)?(a):(b))typedef long long ll;using namespace std;const int N=10050;int n,S,T,ti[N],tim,fa[N],out[N];int ls[N],to[N],ne[N],h[N],tt;int anstime,anslen;char st[310];void add(int a,int b) { to[++tt]=b; ne[tt]=h[a]; h[a]=tt; }void dfs(int x,int ff){ ti[x]=++tim; for(int p=h[x];p;p=ne[p]) { int v=to[p]; if(v==ff) continue; dfs(v,x); }}int main(){ freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%d%d%d",&n,&S,&T); n++; S++; T++; tt=1; for(int i=1;i<n;i++) { int a,b; scanf("%d%d%s",&a,&b,st); a++; b++; ls[a]=strlen(st); fa[a]=b; out[b]++; add(b,a); } fa[1]=0; tim=0; dfs(1,1); if(S==T) { printf("%d\n",ls[S]); printf("0\n"); } else { int fs=S,ft=T; anstime=-out[S]; anslen=0; if(ti[S]<ti[T]) swap(S,T); while(ti[fa[S]]>ti[T]) { anstime+=out[S]; anslen+=ls[S]; S=fa[S]; } anstime+=out[S]; anslen+=ls[S]; S=fa[S]; while(T!=S) { anstime+=out[T]; anslen+=ls[T]; T=fa[T]; } anstime+=out[T]; anslen+=ls[T]; if(ti[T]!=ti[ft]) anstime-=out[ft]; printf("%d\n",anslen); printf("%d\n",anstime); } return 0;}
第二题 路由器
因为这是一棵树,那么,优先处理最深的点一定是最优的,因为点x可以通过x的后代的路由器上网(而最低点不行)。
假如最低点为x,要放路由器,尽可能将其放在比较上的地方father[x][K]。因为既然x能到达,那么father[x][K]的其他后代也一定可以到达。而且放得越上,会对上方的点产生更多的贡献。
解法已经确立了:贪心。
①一种比较暴力的方法,先由最低点x开始,若vis[x]=0,则fa[x][L]装上路由器,ans++。拓展vis[],将可以用这个路由器上网的i的vis[i]标为1.
此方法的时间复杂度较为玄学,应该是不会超时的。vis[]会筛掉很多无用的点(即使重复标记也不会标记很多次的)。
②记录far[]和near[],表示(后代)未联网到当前点的最远的距离,以及最近到当前点的路由器距离。若far[x]+near[x]≤K则fa[x]=-∞,若far[x]=K则必须建立一个路由器(far[x]=-∞,near[x]=0),否则far[x]=(max far[xson])+1,near=(min near[xson])+1。
注:far[]=0,near[]=∞。(此方法是对方法①的一个优化,我也没有想到,是文同学想出来的。)
//方法①:#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define imax(a,b) ((a>b)?(a):(b))#define imin(a,b) ((a<b)?(a):(b))typedef long long ll;using namespace std;const int N=100050;int n,L,ans;int fa[N][12],open[N],dep[N],he,ta;int q[N],la,lb,bu[N];int vis[N],bfstime;bool ok[N];int ne[N<<1],to[N<<1],h[N],tt;void add(int a,int b) { to[++tt]=b; ne[tt]=h[a]; h[a]=tt; }void bfs(int x){ he=ta=1; fa[x][1]=x; open[1]=x; dep[x]=1; vis[x]=1; while(he<=ta) { int u=open[he++]; for(int p=h[u];p;p=ne[p]) { int v=to[p]; if(vis[v]!=0) continue; vis[v]=1; dep[v]=dep[u]+1; fa[v][1]=u; open[++ta]=v; } }}void expand(int x){ la=lb=1; q[1]=x; ok[x]=1; vis[x]=++bfstime; bu[x]=0; while(la<=lb) { int u=q[la++]; if(bu[u]>=L) continue; for(int p=h[u];p;p=ne[p]) { int v=to[p]; if(vis[v]==bfstime) continue; vis[v]=bfstime; bu[v]=bu[u]+1; q[++lb]=v; ok[v]=1; } }}int main(){ freopen("b.in","r",stdin); freopen("b.out","w",stdout); scanf("%d%d",&n,&L); tt=1; for(int i=1;i<n;i++) { int a,b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } bfs(1); for(int i=1;i<=n;i++) for(int j=2;j<=L;j++) fa[i][j]=fa[fa[i][j-1]][1]; bfstime=1; for(int i=ta;i>=1;i--) { int u=open[i]; if(!ok[u]) { ans++; int yu=fa[u][L]; expand(yu); } } printf("%d\n",ans); return 0;}//PS:一开始bfs漏打了vis[x]=1,WA了两个点……
//方法②:#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define imax(a,b) ((a>b)?(a):(b))#define imin(a,b) ((a<b)?(a):(b))typedef long long ll;using namespace std;const int oo=1e9;const int N=100050;int n,L,ans;int open[N],he,ta;int vis[N],fa[N],far[N],near[N];int ne[N<<1],to[N<<1],h[N],tt;void add(int a,int b) { to[++tt]=b; ne[tt]=h[a]; h[a]=tt; }void bfs(int x){ he=ta=1; fa[x]=x; open[1]=x; vis[x]=1; while(he<=ta) { int u=open[he++]; vis[u]=2; for(int p=h[u];p;p=ne[p]) { int v=to[p]; if(vis[v]!=0) continue; vis[v]=1; fa[v]=u; open[++ta]=v; } }}int main(){ freopen("b.in","r",stdin); freopen("b.out","w",stdout); scanf("%d%d",&n,&L); tt=1; for(int i=1;i<n;i++) { int a,b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } bfs(1); ans=0; for(int i=1;i<=n;i++) far[i]=0,near[i]=oo; for(int i=ta;i>=1;i--) { int u=open[i]; if(vis[u]==1) continue; if(far[u]+near[u]<=L) far[u]=-oo; if(far[u]==L) near[u]=0,far[u]=-oo,ans++; far[fa[u]]=imax(far[u]+1,far[fa[u]]); near[fa[u]]=imin(near[u]+1,near[fa[u]]); } if(far[1]>0) ans++; printf("%d\n",ans); return 0;}
第三题 骨牌游戏
X
阅读全文
1 0
- NOIP2017提高组模拟赛 10 (总结)
- NOIP2017提高组模拟赛4 (总结)
- NOIP2017提高组模拟赛5 (总结)
- NOIP2017提高组模拟赛 7(总结)
- NOIP2017提高组模拟赛 8(总结)
- NOIP2017提高组模拟赛 9 (总结)
- NOIP2017提高组 模拟赛13(总结)
- NOIP2017提高组 模拟赛15(总结)
- NOIP2017提高组 模拟赛16(总结)
- NOIP2017提高组 模拟赛17(总结)
- NOIP2017提高组 模拟赛18(总结)
- NOIP2017提高组 模拟赛19(总结)
- NOIP2017提高组 模拟赛20(总结)
- NOIP2017提高组 模拟赛21(总结)
- NOIP2017提高组 模拟赛23(总结)
- NOIP2017提高组 模拟赛24(总结)
- NOIP2017提高组 模拟赛 26(总结)
- NOIP2017提高组 模拟赛 27(总结)
- stl string常用函数
- Spring中用到的设计模式
- fiddler的使用
- 安卓数据保存登录状态
- java基础知识点汇总
- NOIP2017提高组模拟赛 10 (总结)
- activeMQ主要的几类集群部署方式
- 【JVM】类文件结构
- 2017 随笔一
- SpringBoot Mock测试
- VS2010利用ATL创建COM dll,编译时报错
- DEV gridview 捕获行双击事件
- JZOJ 3765【BJOI2014】想法
- 前端开发-js正则总结