题目描述

  有一棵\(n\)个点的树,还有\(m\)个物品。

  你要把每个物品放在树上的一个点上(两个物品可以放在同一个点)。

  有\(q\)个限制:\(a,b\)两个物品在路上的最短路经过\(c\)。

  要你构造一组合法的方案。

  \(n,m\leq 250\)

题解

  很容易想到2-sat。

  但是把点看成"物品\(x\)放在\(y\)上"会找不到合法解。

  所以要把点看成“物品\(x\)在以\(y\)为根的子树内”,这样根就是必须选的。

  连边的话(下面只列出一半的边):\(x\rightarrow f_x,x\rightarrow !y\)(\(y\)是\(x\)的兄弟)(这些边可以弄一些前缀后缀的点优化)

  和询问有关的:

  1.\(a\neq b\):\((a,x)\rightarrow !(b,x)\)(\(x\)是\(c\)的儿子),\(!(a,c)\rightarrow (b,c)\)。

  2.\(a=b\):\(!(a,c)\rightarrow(a,c)\),\((a,x)\rightarrow !(a,x)\)(\(x\)是\(c\)的儿子)。

  点数为\(O(nm)\)

  边数为\(O(nm^2)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
struct graph
{
int h[400010];
int v[40000010];
int t[40000010];
int n;
graph()
{
n=0;
memset(h,0,sizeof h);
}
void add(int x,int y)
{
n++;
v[n]=y;
t[n]=h[x];
h[x]=n;
}
};
graph g;
vector<int> t[260],t2;
int n,m,q;
int id(int x,int y)//x=物品,y=点
{
return (y-1)*m+x;
}
int cnt;
int pre[260],suf[260];
void add0(int k1,int x,int k2,int y)
{
g.add(id(k1,x)*2-1,id(k2,y)*2);
g.add(id(k2,y)*2-1,id(k1,x)*2);
}
void add4(int k1,int x,int k2,int y)
{
g.add(id(k1,x)*2,id(k2,y)*2-1);
g.add(id(k2,y)*2,id(k1,x)*2-1);
}
void add1(int k1,int x,int k2,int y)
{
g.add(id(k1,x)*2-1,id(k2,y)*2-1);
g.add(id(k2,y)*2,id(k1,x)*2);
}
void add2(int k,int x)
{
g.add(id(k,x)*2,id(k,x)*2-1);
}
void add3(int k,int x)
{
g.add(id(k,x)*2-1,id(k,x)*2);
}
int f[300];
int d[300];
void dfs(int x,int fa,int dep)
{
t2.clear();
f[x]=fa;
d[x]=dep;
for(auto v:t[x])
if(v!=fa)
t2.push_back(v);
t[x]=t2;
for(auto v:t[x])
dfs(v,x,dep+1);
}
int b[400010];
int e[400010];
int ti,tot,top;
int st[400010];
int dfn[400010];
int low[400010];
int c[300][300][300];
void dfs(int x)
{
low[x]=dfn[x]=++ti;
st[++top]=x;
b[x]=1;
for(int i=g.h[x];i;i=g.t[i])
{
if(b[g.v[i]]!=2)
{
if(!b[g.v[i]])
dfs(g.v[i]);
low[x]=min(low[x],low[g.v[i]]);
}
}
if(low[x]>=dfn[x])
{
int v;
tot++;
do
{
v=st[top--];
e[v]=tot;
b[v]=2;
}
while(v!=x);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
#endif
scanf("%d%d%d",&n,&m,&q);
int x,y,z;
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
t[x].push_back(y);
t[y].push_back(x);
}
dfs(1,0,1);
cnt=n;
for(int i=1;i<=n;i++)
{
if(i!=1)
for(int k=1;k<=m;k++)
add1(k,i,k,f[i]);
int sz=t[i].size();
for(int j=0;j<sz;j++)
{
pre[j]=++cnt;
for(int k=1;k<=m;k++)
add1(k,t[i][j],k,pre[j]);
if(j)
for(int k=1;k<=m;k++)
add1(k,pre[j-1],k,pre[j]);
}
for(int j=sz-1;j>=0;j--)
{
suf[j]=++cnt;
for(int k=1;k<=m;k++)
add1(k,t[i][j],k,suf[j]);
if(j!=sz-1)
for(int k=1;k<=m;k++)
add1(k,suf[j+1],k,suf[j]);
}
for(int j=0;j<sz;j++)
{
if(j)
for(int k=1;k<=m;k++)
add0(k,t[i][j],k,pre[j-1]);
if(j!=sz-1)
for(int k=1;k<=m;k++)
add0(k,t[i][j],k,suf[j+1]);
}
}
for(int i=1;i<=m;i++)
add2(i,1);
memset(b,0,sizeof b);
for(int i=1;i<=q;i++)
{
scanf("%d%d%d",&x,&y,&z);
if(x>y)
swap(x,y);
if(c[x][y][z])
continue;
c[x][y][z]=1;
if(x==y)
{
add2(x,z);
for(auto v:t[z])
add3(x,v);
}
else
{
for(auto v:t[z])
add0(x,v,y,v);
add4(x,z,y,z);
}
}
ti=0;
tot=0;
top=0;
for(int i=1;i<=2*m*cnt;i++)
if(!b[i])
dfs(i);
for(int i=1;i<=m;i++)
{
int ans=1;
for(int j=1;j<=n;j++)
if(e[2*id(i,j)-1]<e[2*id(i,j)])
if(d[j]>d[ans])
ans=j;
printf("%d ",ans);
}
return 0;
}

【XSY2750】Mythological V 2-sat的更多相关文章

  1. 【XSY2786】Mythological VI 数学

    题目描述 有\(1\sim n\)一共\(n\)个数.保证\(n\)为偶数. 你要把这\(2n\)个数两两配对,一共配成\(n\)对.每一对的权值是他们两个数的和. 你想要知道这\(n\)对里最大的权 ...

  2. 【XSY2751】Mythological IV 线性插值

    题目描述 已知\(f(x)\)为\(k\)次多项式. 给你\(f(0),f(1),\ldots,f(k)\),求 \[ \sum_{i=1}^nf(i)q^i \] \(k\leq 500000,n\ ...

  3. 【转】grep -v grep

    1.grep 是查找含有指定文本行的意思,比如grep test 就是查找含有test的文本的行 2.grep -v 是反向查找的意思,比如 grep -v grep 就是查找不含有 grep 字段的 ...

  4. MT【330】u,v,w法

    已知$a^2+b^2+c^2=1$求$abc(a+b+c)$的最小值.(2018辽宁预赛解答压轴题) 不妨设$a+b+c=3u,ab+bc+ca=3v^2,abc=w^3$,令$u^2=tv^2$要求 ...

  5. 【XSY2787】Mythological VII 贪心

    题目描述 有两个指针\(l,r\),初始时\(l=r=k\) 给你\(a_1,\ldots,a_n\),你要移动\(l,r\),\(l\)只能每次向左移一个数,\(r\)只能向右移一个数,要求任意时刻 ...

  6. 【学时总结】◆学时·V◆ 逆元法

    ◆学时·V◆ 逆元法 □算法概述□ 逆元运算是模运算中的一个技巧,一般用于解决模运算的除法问题.模运算对于加.减.乘是有封闭性的,即 (a±b)%m=a%m±b%m,以及 (a×b)%m=a%m×b% ...

  7. 【原创】如何通过-y和-v使用库文件

    在进行仿真时,经常遇到设计代码中需要调用一些标准的库文件,但是在设计的编译列表filelist中却没有相应的库文件,这时为了完成仿真,需要设计人员提供对应的库文件或者库文件所在的路径,然后仿真时将这些 ...

  8. 【pwn】V&N2020 公开赛 simpleHeap

    [pwn]V&N2020 公开赛 simpleHeap 1.静态分析 首先libc版本是ubuntu16的2.23版本,可以去buu的资源处下载 然后checksec一下,保护全开 拖入IDA ...

  9. 【Leetcode】1340. Jump Game V 【动态规划/记忆性搜索】

    Given an array of integers arr and an integer d. In one step you can jump from index i to index: i + ...

随机推荐

  1. Method not found: !!0[] System.Array.Empty()错误

    最近由于公司项目需要将之前支持的TLS1.0改成更安全的TLS1.2,而公司现有项目都是老系统,有的是.NET FrameWork 4.0,有的是.NET FrameWork3.5,但是TLS1.2默 ...

  2. Python遇到问题总结

    1.list的集合 循环删除一个list数据时,会遇到一丢丢问题,详情看Python的list循环遍历中,删除数据的正确方法 但是,里面说的要反转一下list集合,可以用a[::-1]这种方法. &g ...

  3. H5 29-div和span标签

    29-div和span标签 --> 努力到无能为力, 拼搏到感动自己 --> 我是div 我是div 我是span 我是span --> --> 我是段落 我是标题 --> ...

  4. Python—元类

    什么是元类? 元类是类的类,是类的模板 元类是用来控制如何创建类的,正如类是创建对象的模板一样,而元类的主要目的是为了控制类的创建行为 元类的实例化的结果为我们用class定义的类,正如类的实例为对象 ...

  5. [2018福大至诚软工助教]alpha阶段小结

    [2018福大至诚软工助教]alpha阶段小结 一.得分 1. 冲刺(7次 Scrum) 150分 1)第1篇(25分) 项目 评分标准 各个成员在 Alpha 阶段认领的任务 (6分)视详细程度给分 ...

  6. Eclipse中Git的使用以及IDEA中Git的使用

    一.Eclipse中Git解决冲突步骤: 1.进行文件对比,将所有的文件添加到序列. 2.commit文件到本地仓库. 3.pull将远程仓库的代码更新到本地,若有冲突则会所有的文件显示冲突状态(真正 ...

  7. 【kindle笔记】之 《明朝那些事儿》-2018-7-1

    [kindle笔记]读书记录-总 最近在读这本书.之前在微信读书里断断续续读过,读到深处还想蹦起来做笔记那种.后来种种原因断了,再没续上. 现在又开始啦.最近还在重八兄造反阶段,还很早呢,有时候晚上玩 ...

  8. 爬虫——xpath

    1.什么是xpath? Xpath,全称XML Path Language,即XML路径语言.它是一门在XML之后查找信息的语言,也同样适用于HTML文档的搜索.在做爬虫的时候,我们用XPath语言来 ...

  9. 逻辑斯特回归tensorflow实现

    calss #!/usr/bin/python2.7 #coding:utf-8 from __future__ import print_function import tensorflow as ...

  10. WorldCount代码检查与优化——软件测试第三次作业

    合作者:201631062222,201631062232 代码地址:https://gitee.com/biubiubiuLYQ/ceshi_secend 本次作业链接地址:https://edu. ...