【XSY2750】Mythological V 2-sat
题目描述
有一棵\(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的更多相关文章
- 【XSY2786】Mythological VI 数学
题目描述 有\(1\sim n\)一共\(n\)个数.保证\(n\)为偶数. 你要把这\(2n\)个数两两配对,一共配成\(n\)对.每一对的权值是他们两个数的和. 你想要知道这\(n\)对里最大的权 ...
- 【XSY2751】Mythological IV 线性插值
题目描述 已知\(f(x)\)为\(k\)次多项式. 给你\(f(0),f(1),\ldots,f(k)\),求 \[ \sum_{i=1}^nf(i)q^i \] \(k\leq 500000,n\ ...
- 【转】grep -v grep
1.grep 是查找含有指定文本行的意思,比如grep test 就是查找含有test的文本的行 2.grep -v 是反向查找的意思,比如 grep -v grep 就是查找不含有 grep 字段的 ...
- 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$要求 ...
- 【XSY2787】Mythological VII 贪心
题目描述 有两个指针\(l,r\),初始时\(l=r=k\) 给你\(a_1,\ldots,a_n\),你要移动\(l,r\),\(l\)只能每次向左移一个数,\(r\)只能向右移一个数,要求任意时刻 ...
- 【学时总结】◆学时·V◆ 逆元法
◆学时·V◆ 逆元法 □算法概述□ 逆元运算是模运算中的一个技巧,一般用于解决模运算的除法问题.模运算对于加.减.乘是有封闭性的,即 (a±b)%m=a%m±b%m,以及 (a×b)%m=a%m×b% ...
- 【原创】如何通过-y和-v使用库文件
在进行仿真时,经常遇到设计代码中需要调用一些标准的库文件,但是在设计的编译列表filelist中却没有相应的库文件,这时为了完成仿真,需要设计人员提供对应的库文件或者库文件所在的路径,然后仿真时将这些 ...
- 【pwn】V&N2020 公开赛 simpleHeap
[pwn]V&N2020 公开赛 simpleHeap 1.静态分析 首先libc版本是ubuntu16的2.23版本,可以去buu的资源处下载 然后checksec一下,保护全开 拖入IDA ...
- 【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 + ...
随机推荐
- Pointcut 笔记
教程 https://blog.csdn.net/kkdelta/article/details/7441829 http://www.cnblogs.com/youse/p/6564524.html ...
- 接口自动化框架(Pytest+request+Allure)
前言: 接口自动化是指模拟程序接口层面的自动化,由于接口不易变更,维护成本更小,所以深受各大公司的喜爱. 接口自动化包含2个部分,功能性的接口自动化测试和并发接口自动化测试. 本次文章着重介绍第一种, ...
- Python-爬虫小例子-55
import re from urllib.request import urlopen def getPage(url): response = urlopen(url) return respon ...
- HDU - 1698 线段树区间修改,区间查询
这就是很简单的基本的线段树的基本操作,区间修改,区间查询,对区间内部信息打上laze标记,然后维护即可. 我自己做的时候太傻逼了...把区间修改写错了,对给定区间进行修改的时候,mid取的是节点的左右 ...
- 抽象代数-p22商群
G/e={g{e}|g∈G}={{g}|g∈G}=G G/G={gG|g∈G}={G} (gG=G左乘g是G上的双射,它的逆映射是左乘g^-1) 所以 G/G 只有一个元素,所有G 就只能是 ...
- 用WSDL4J解析types标签中的内容
WSDL4J是一种用来解析WSDL文本的常用工具. 但网络上用WSDL4J来解析wsdl文档complexType标签中内容的问题一大堆也没有有效的解决方法.今天在我“遍历”wsdl4j的api文档和 ...
- GFS浅析
1 . 简介 GFS, Big Table, Map Reduce称为Google的三驾马车,是许多基础服务的基石 GFS于2003年提出,是一个分布式的文件系统,与此前的很多分布式系统的前提假设存在 ...
- mysql之整合ssm多数据源配置
一,基于SSM框架的多数据源配置 1.创建DynamicDataSourceHolder用于持有当前线程中使用的数据源标识 public class DynamicDataSourceHolder { ...
- mysql 查看版本
查看mysql版本的四种方法 - 风生水起 - 博客园 http://www.cnblogs.com/end/archive/2011/10/18/2216461.html 查看mysql数据库版本方 ...
- array_column函数
<?php $arr = [ [ 'id'=>1, 'name'=>'wang', 'age'=>10 ], [ 'id'=>2, 'name'=>'yong', ...