Codeforces 947F. Public Service 构造
原文链接https://www.cnblogs.com/zhouzhendong/p/CF947F.html
近5K码量构造题,CF血腥残暴!
题解
这里先定义 $FT(k)$ 表示一个菊花树多 k 个点且这 k 个点都不在菊花的中心上。记 $C(x)$ 表示与 $x$ 直接相连的节点( x 为叶子的时候答案唯一)。
例如下面的一棵树就是一个 $FT(4)$ ,其中红色区域的是菊花,多出来的 4 个点在绿色区域。

首先,这两棵树如果有任意一棵是 $FT(0)$ 则一定无解。因为如果有 $FT(0)$ 那么菊花中心的点的度数已经满了,在另一颗树中无论匹配什么点都不能有出边,GG。
否则,如果有任意一棵是 $FT(1)$ ,那么我们可以给出构造:
在另一棵树中找一个叶子 $b$,让菊花中心匹配它;假设 $FT(1)$ 中多出来的那个是节点 $a$,让它匹配 $C(b)$;让 $C(a)$ 找一个不与 $b$ 连通的节点对应(由于两棵树都不是 $FT(0)$ ,所以一定可以找到这样的节点);剩下的节点随便匹配。
否则,两棵树都至少是 $FT(2)$ 。考虑在第一棵树中分别找出两个叶子(设为u1,u2),保证这两个叶子的父亲不同且删除这两个叶子之后剩下的树不是 $FT(0)$ (由于这棵树至少是 $FT(2)$,所以必然存在一种方案),在第二棵树中也找出两个这样的点(设为v1,v2);在两棵树中分别删除选出的点,然后递归处理剩下的树的匹配;接下来考虑匹配(u1,v1) (u2,v2) 是否可行,假如不可行(就是 C(u1) 与 C(v1) 匹配了,或者 C(v2) 与 C(u2) 匹配了),那么交换 v1,v2,也就是匹配 (u1,v2) (u2,v1),简单画个图就可以证明这两种匹配中至少有一种是可行的。
对于点数小于等于 5 的,直接暴力枚举匹配就好了。
这样我们就找到了一种构造方法。
请您写一写这题代码。
祝您身体健康。
代码
听说用变量名xza可以让你更快的AC题目,我试了试,果然变快了。把这个技巧传到998244353个qq群,才能表现你膜拜xza的赤诚之心,xza会告诉你他AK的秘诀!
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
using namespace std;
typedef long long LL;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=10005;
int n;
map <int,int> mpa[N],mpb[N];
vector <int> a[N],b[N];
int p[N];
void Getp(vector <int> &A,vector <int> &B){
static int ga[10][10],gb[10][10],ya[N],yb[N];
clr(ga),clr(gb);
memset(ya,-1,sizeof ya);
memset(yb,-1,sizeof yb);
int m=A.size(),cnt=1;
for (int i=1;i<=m;i++)
cnt*=i;
for (int i=0;i<m;i++)
ya[A[i]]=i;
for (int i=0;i<m;i++)
yb[B[i]]=i;
for (int i=0;i<m;i++){
int x=A[i];
for (auto y : a[x])
if (ya[y]!=-1)
ga[i][ya[y]]=1;
}
for (int i=0;i<m;i++){
int x=B[i];
for (auto y : b[x])
if (yb[y]!=-1)
gb[i][yb[y]]=1;
}
vector <int> id(0);
for (int i=0;i<m;i++)
id.push_back(i);
while (cnt--){
int flag=1;
for (int i=0;i<m&&flag;i++)
for (int j=0;j<m&&flag;j++)
if (ga[i][j]&&gb[id[i]][id[j]])
flag=0;
if (flag){
for (int i=0;i<m;i++)
p[A[i]]=B[id[i]];
return;
}
next_permutation(id.begin(),id.end());
}
assert(0);
}
void vec_remove(vector <int> &v,int u){
int flag=0;
for (int i=0;i<(int)v.size();i++)
if (v[i]==u){
swap(v[i],v.back());
v.pop_back();
flag=1;
}
assert(flag);
}
vector <int> A,B;
int ctag[N];
int solve(){
A.clear(),B.clear();
int ra=0,rb=0;
for (int i=1;i<=n;i++){
if (!a[i].empty())
A.push_back(i);
if (!b[i].empty())
B.push_back(i);
if (a[i].size()>a[ra].size())
ra=i;
if (b[i].size()>b[rb].size())
rb=i;
}
int m=A.size();
if ((int)a[ra].size()+1==m||(int)b[rb].size()+1==m)
return 0;
if (m<=5)
return Getp(A,B),1;
if ((int)a[ra].size()+1==m-1){
int ai=0;
for (int i=0;i<m&&!ai;i++)
if (a[A[i]].size()==1&&a[A[i]][0]!=ra)
ai=A[i];
int bi=0;
for (int i=0;i<m&&!bi;i++)
if (b[B[i]].size()==1)
bi=B[i];
p[ra]=bi;
assert(!b[bi].empty());
int bf=p[ai]=b[bi][0];
int af=a[ai][0],afp=0;
vec_remove(A,ra);
vec_remove(A,ai);
vec_remove(B,bi);
vec_remove(B,bf);
clr(ctag);
for (auto by : b[bf])
ctag[by]=1;
for (int i=0;i<m-2&&!afp;i++)
if (!ctag[B[i]])
afp=B[i];
p[af]=afp;
vec_remove(A,af);
vec_remove(B,afp);
for (int i=0;i<m-3;i++)
p[A[i]]=B[i];
return 1;
}
if ((int)b[rb].size()+1==m-1){
int ai=0;
for (int i=0;i<m&&!ai;i++)
if (a[A[i]].size()==1)
ai=A[i];
int bi=0;
for (int i=0;i<m&&!bi;i++)
if (b[B[i]].size()==1&&b[B[i]][0]!=rb)
bi=B[i];
p[ai]=rb;
assert(!a[ai].empty());
p[a[ai][0]]=bi;
int af=a[ai][0];
int bf=b[bi][0],bfp=0;
vec_remove(B,rb);
vec_remove(B,bi);
vec_remove(A,ai);
vec_remove(A,af);
clr(ctag);
for (auto ay : a[af])
ctag[ay]=1;
for (int i=0;i<m-2&&!bfp;i++)
if (!ctag[A[i]])
bfp=A[i];
p[bfp]=bf;
vec_remove(B,bf);
vec_remove(A,bfp);
for (int i=0;i<m-3;i++)
p[A[i]]=B[i];
return 1;
}
int xa=0,ya=0,xb=0,yb=0;
int xza=0,yza=0,xzb=0,yzb=0;
for (int i=0;i<m&&!xa;i++)
if (a[A[i]].size()==1&&a[A[i]][0]!=ra)
xa=A[i];
if ((int)a[ra].size()+2==m-1){
for (int i=0;i<m&&!ya;i++)
if (a[A[i]].size()==1&&a[A[i]][0]==ra)
ya=A[i];
}
else {
for (int i=0;i<m;i++)
if (a[A[i]].size()==1&&(a[A[i]][0]!=ra||!ya)&&a[A[i]][0]!=a[xa][0])
ya=A[i];
}
for (int i=0;i<m&&!xb;i++)
if (b[B[i]].size()==1&&b[B[i]][0]!=rb)
xb=B[i];
if ((int)b[rb].size()+2==m-1){
for (int i=0;i<m&&!yb;i++)
if (b[B[i]].size()==1&&b[B[i]][0]==rb)
yb=B[i];
}
else {
for (int i=0;i<m;i++)
if (b[B[i]].size()==1&&(b[B[i]][0]!=rb||!yb)&&b[B[i]][0]!=b[xb][0])
yb=B[i];
}
xza=a[xa][0];
yza=a[ya][0];
xzb=b[xb][0];
yzb=b[yb][0];
#define rm vec_remove
#define rme(a,x,y) rm(a[x],y),rm(a[y],x)
rme(a,xa,xza);
rme(a,ya,yza);
rme(b,xb,xzb);
rme(b,yb,yzb);
#undef rme
#undef rm
int res=solve();
if (!res)
return 0;
if ((p[xza]==xzb&&mpa[xa][xza]&&mpb[xb][xzb])||(p[yza]==yzb&&mpa[ya][yza]&&mpb[yb][yzb]))
swap(xb,yb),swap(xzb,yzb);
assert(!(p[xza]==xzb&&mpa[xa][xza]&&mpb[xb][xzb])&&!(p[yza]==yzb&&mpa[ya][yza]&&mpb[yb][yzb]));
p[xa]=xb,p[ya]=yb;
return 1;
}
int main(){
n=read();
for (int i=1;i<n;i++){
int x=read(),y=read();
a[x].push_back(y);
a[y].push_back(x);
mpa[x][y]=mpa[y][x]=1;
}
for (int i=1;i<n;i++){
int x=read()-n,y=read()-n;
b[x].push_back(y);
b[y].push_back(x);
mpb[x][y]=mpb[y][x]=1;
}
int res=solve();
if (!res)
puts("No");
else {
puts("Yes");
for (int i=1;i<=n;i++)
printf("%d ",p[i]+n);
}
return 0;
}
Codeforces 947F. Public Service 构造的更多相关文章
- Codeforces 1383D - Rearrange(构造)
Codeforces 题面传送门 & 洛谷题面传送门 一道不算困难的构造,花了一节英语课把它搞出来了,题解简单写写吧( 考虑从大往小加数,显然第三个条件可以被翻译为,每次加入一个元素,如果它所 ...
- Codeforces 549B. Looksery Party[构造]
B. Looksery Party time limit per test 1 second memory limit per test 256 megabytes input standard in ...
- codeforces 323A. Black-and-White Cube 构造
输入n 1 <= n <= 100 有一个n * n * n 的立方体,由n ^ 3 个1 * 1 * 1 的单位立方体构成 要用white 和 black 2种颜色来染这n ^ 3个立方 ...
- Codeforces Gym 100531I Instruction 构造
Problem I. Instruction 题目连接: http://codeforces.com/gym/100531/attachments Description Ingrid is a he ...
- codeforces 22C System Administrator(构造水题)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud System Administrator Bob got a job as a s ...
- Codeforces 353D Queue(构造法)
[题目链接] http://codeforces.com/contest/353/problem/D [题目大意] 10^6个男女排队,每一秒,如果男生在女生前面,即pos[i]是男生,pos[i+1 ...
- Codeforces 482 - Diverse Permutation 构造题
这是一道蛮基础的构造题. - k +(k - 1) -(k - 2) 1 + k , 1 , k , 2, ....... ...
- [ An Ac a Day ^_^ ] CodeForces 468A 24 Game 构造
题意是让你用1到n的数构造24 看完题解感觉被样例骗了…… 很明显 n<4肯定不行 然后构造出来4 5的组成24的式子 把大于4(偶数)或者5(奇数)的数构造成i-(i-1)=1 之后就是无尽的 ...
- Codeforces 1045E. Ancient civilizations 构造 计算几何 凸包
原文链接https://www.cnblogs.com/zhouzhendong/p/CF1045E.html 4K码量构造题,CF血腥残暴! 题解 首先,如果所有点颜色相同,那么直接连个菊花搞定. ...
随机推荐
- vue2.0实现过滤
vue1.0和vue2.0差别还是挺多的,之前的vue1.0还有过滤器功能,到了2.0过滤器只能通过自己编写.以下是写的一个小demo: HTML <div id="app" ...
- [HackerRank]New Year Chaos[UNDONE]
Input (stdin)Download 2 8 5 1 2 3 7 8 6 4 8 1 2 5 3 7 8 6 4 Your Output (stdout) Too chaotic Too cha ...
- 配置ssh免密登录服务器
当前服务器环境为ubantu 14.04 一.本地 ①生成id_rsa id_rsa.pub ssh-keygen -t rsa -C "xxxxx@xxxxx.com" ss ...
- NetSarang软件中nssock2.dll模块被植入恶意代码技术分析与防护方案
原文地址:http://blog.nsfocus.net/nssock2-dll-module-malicious-code-analysis-report/ NetSarang是一家提供安全连接解决 ...
- Java斗地主案例、异常和自定义异常整理
模拟斗地主洗牌发牌 1.1 案例介绍 按照斗地主的规则,完成洗牌发牌的动作. 具体规则: 1. 组装54张扑克牌 2. 将54张牌顺序打乱 3. 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张 ...
- 剑指Offer_编程题_25
题目描述 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head.(注意,输出结果中请不要返回参数中的节点引用,否 ...
- Redis知识整理
Redis知识整理 转自:https://www.cnblogs.com/rjzheng/p/9096228.html 1.单线程模型 Redis客户端对服务端的每次调用都经历了发送命令,执行命令,返 ...
- Entity Framework入门教程(10)---离线场景保存和删除实体/实体图集
离线场景保存和删除实体/实体图集 这一节的内容是在离线场景中保存实体和实体图集 在离线场景中,当我们保存一个离线的实体图集或一个单独的离线实体时,我们需要做两件事.首先,我们要把实体附加到新的上下文中 ...
- Vim使用技巧汇总
一 写在开头 1.1 本文内容 Vim使用技巧与学习资源汇总. 二 Vim学习资源 1. Vimtutor 2. Vim中文帮助(http://vimcdoc.sourceforge.net/doc/ ...
- JavaScript 日期和时间基础知识
前言 学习Date对象之前,首先要先了解关于日期和时间的一些知识.比如,闰年.UTC等等.深入了解这些,有助于更好地理解javascript中的Date对象. 标准时间 一般而言的标准时间是指GMT和 ...