省选武汉联测 13 题解
Posted gtm1514
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了省选武汉联测 13 题解相关的知识,希望对你有一定的参考价值。
省选模拟赛俩构造一交互挺 nm 逆天。赛后题解区就一句 Surprise!!! 没题解也挺 nm 逆天。那建议组题人的马先消失一下。
这时候就体现学长博客的重要性了。搜关键词搜到三个:yspm,房屋,Max。膜拜以上大师。
然后犇犇里在倡议把某人踢出歌单。保持中立。
构树
签到题。\\(O(n^2)\\) 枚举点,能连就连。容易证明贪心是对的。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
int n,fa[1010],a[1010],b[1010];
int g[1010][1010];
vector<pair<int,int> >v;
int find(int x)
return x==fa[x]?fa[x]:fa[x]=find(fa[x]);
void merge(int x,int y)
g[x][y]=g[y][x]=1;
if(x>y)swap(x,y);
if(find(x)==find(y))return;
v.push_back(make_pair(x,y));
fa[find(x)]=find(y);
int main()
scanf("%d",&n);
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i],&b[i]);
if((find(a[i])==find(i)&&!g[a[i]][i])||(find(b[i])==find(i)&&!g[b[i]][i]))
puts("-1");return 0;
merge(i,a[i]),merge(i,b[i]);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(find(i)==find(j))continue;
if(a[i]<=j&&j<=b[i]&&a[j]<=i&&i<=b[j])merge(i,j);
if(v.size()!=n-1)
puts("-1");return 0;
for(pair<int,int>p:v)printf("%d %d\\n",p.first,p.second);
return 0;
交互
赛时读错题了。怎么读错的和你一样。问了一圈一车读错的。
读对题了其实好像不难。
首先显然 \\(1\\) 号节点没左儿子。设确定了 \\(1\\sim i-1\\) 节点的子树,那么对于 \\(i\\) 节点:
- 有右儿子:此时知道左端点是自己,向下递归。
- 没有右儿子:知道了所有的左边子树,那么可以直接连上左儿子返回这个子树。
代码很短。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include "interact.h"
using namespace std;
int solve(int rt,int L,int &R)
R=rt;
if(query(rt,L,R))return rt;
for(int ls=0,rs;;ls=rs)
rs=solve(R+1,rt+1,R);
if(ls)report(ls,rs);
if(query(rt,L,R))
report(rt,rs);
return rt;
void guess(int n)
int R=0;
for(int ls=0,rs;R<n;ls=rs)
rs=solve(R+1,1,R);
if(ls)report(ls,rs);
构图
场上就嗯想不到。还是菜的真实。
枚举度数 \\(k\\) 的点的个数,然后贪心往后连度数最小的点。剩下的度数不是 \\(k\\) 的点如果度数不到 \\(k+1\\) 就内部连边。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
int n,k,d[1010];
vector<pair<int,int> >g;
queue<int>q;
void solve(int i)
vector<pair<int,int> >ret;
for(int j=i+1;j<=n;j++)q.push(j),d[j]=0;
for(int j=1;j<=i;j++)
for(int cnt=1;cnt<=k;cnt++)
int x=q.front();q.pop();d[x]++;q.push(x);
ret.push_back(make_pair(x,j));
while(!q.empty())
int x=q.front();q.pop();
if(d[x]+q.size()<=k)return;
while(d[x]<=k)
int y=q.front();q.pop();
d[x]++;d[y]++;q.push(y);
ret.push_back(make_pair(x,y));
if(g.empty()||ret.size()<g.size())swap(g,ret);
int main()
scanf("%d%d",&n,&k);
for(int i=1;i<=n-k;i++)solve(i);
printf("%d\\n",(int)g.size());
for(pair<int,int>p:g)printf("%d %d\\n",p.first,p.second);
return 0;
快踩
以上是关于省选武汉联测 13 题解的主要内容,如果未能解决你的问题,请参考以下文章