【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 + ...
随机推荐
- 设计模式之单例模式(C#)
本文来自于本人个人微信公众号,欢迎关注本人微信公众号,二维码附在文章末尾~~~ 一直都特别羡慕能写文章的人,但是由于本人比较懒再加上写文章功底实在是just so so,所以就一搁再搁,最近突然觉得自 ...
- 动态规划-LCS最长公共子序列
#include<iostream> #include<cstdio> #include<cstring> #include<string> using ...
- git在vs2017中的使用
对于习惯了右键提交源代码的道友来说,敲命令行真的蓝瘦香菇.所幸17里集成了Git插件,用起来还是挺方便的. 1.本地安装git,工具还是要有的,主要用于配置环境,ssh配置一下.就不用每次都去连接了. ...
- Ubuntu Linux Recovery Mode
在安全模式/修復模式有以下的選項︰resume Resume normal boot繼續正常啟動作業,供不小心誤入此選單的使用者開機使用.(继续以正常模式启动) clean Try to make f ...
- vue动态class——实现tag的选中状态
vue动态class——实现tag的选中状态 <template> <div class="common-nav"> <div class=" ...
- Jenkins [Error] at org.codehaus.cargo.container.tomcat.internal.AbstractTomcatManagerDeployer.redeploy(AbstractTomcatManagerDeployer.java:192)
Deploying /root/.jenkins/workspace/zgg-crm-pre/target/crm.war to container Tomcat 7.x Remote with co ...
- jmeter压测参数设定(转)
jmeter压测参数设定 一.基本公式 线程数 = QPS * time: 注:QPS--每秒完成请求的个数:time--每个请求响应完成平均需要时间: 故QPS * time就是所有请求完成响应所需 ...
- 给网站配置免费的HTTS证书
取经自思否:https://segmentfault.com/a/1190000015231137 https 的网站 搜索引擎 会优先收录,所以就抽时间记录下配置博客的过程,各种找资料,终于给我找到 ...
- 一次linux问题分析原因的简要记录
1. 这边功能测试 一个linux服务器 4c 16g的内存 发现总是出现异常. dotnet run 起来的一个 程序 总是会被killed 现象为: 2. 一开始怀疑是 打开的文件描述符过多 引起 ...
- mybatis两种开发方式
本文首先讲解从JDBC到mybatis的演变过程,然后是使用mybatis进行开发的两种方式. 一 JDBC的使用及其优化 1.使用JDBC进行数据库操作 加载JDBC驱动: 建立并获取数据库连接: ...