bzoj2215: [Poi2011]Conspiracy 2-sat

链接

https://www.lydsy.com/JudgeOnline/problem.php?id=2215

思路

一个点的属性为去当同谋者和后勤两种

求出一种方案来很简单(只需要用简单的2-sat)

我们发现一条特别重要的性质:

一个方案只会由已经求出的其他任意一种方案改变一方的一个人得来

(基本看出来就稳了)

因为两个人不能同时过去(显然)

那么我们先求出一种方案

然后统计ok[i],表示i到对面冲突的点的个数

显然只有几种情况(大力分情况讨论)

①.一个间谍去后勤

②.一个后勤区去间谍

就是ok==0的个数(注意双方都不能为0个人)

③.间谍和后勤互换(容易发现交换的两个人一定一个是0,一个是1)

好了。

错误

tarjan求方案的方向居然写反了、、、

还有mp的i+n没减n

代码

#include <iostream>
#include <cstdio>
#include <vector>
#define iter vector<int>::iterator
const int N=5007;
using namespace std;
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int n,ok[N<<1],dsr;
bool mp[N][N];
vector<int> ans[2];
struct node {
int v,nxt;
}e[N*N];
int head[N<<1],tot;
void add(int u,int v) {
e[++tot].v=v;
e[tot].nxt=head[u];
head[u]=tot;
}
int dfn[N<<1],low[N<<1],stak[N<<1],top,cnt,belong[N<<1],vis[N<<1];
void tarjan(int u) {
dfn[u]=low[u]=++cnt;
vis[u]=1;
stak[++top]=u;
for(int i=head[u];i;i=e[i].nxt) {
int v=e[i].v;
if(!dfn[v]) {
tarjan(v);
low[u]=min(low[u],low[v]);
} else if(vis[v]) {
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]) {
belong[0]++;
while(stak[top]!=u) {
vis[stak[top]]=0;
belong[stak[top]]=belong[0];
top--;
} top--;
vis[u]=0;
belong[u]=belong[0];
}
}
int main() {
n=read();
for(int i=1;i<=n;++i) {
int k=read();
for(int j=1;j<=k;++j) mp[i][read()]=1;
}
for(int i=1;i<=n;++i) {
for(int j=1;j<i;++j) {
if(mp[i][j]) {
add(i,j+n),add(j,i+n);
} else {
add(i+n,j),add(j+n,i);
}
}
}
for(int i=1;i<=n+n;++i)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;++i) {
if(belong[i]==belong[i+n]) {
puts("0");
return 0;
}
}
for(int i=1;i<=n;++i) {
if(belong[i] < belong[i+n]) ans[0].push_back(i);
else ans[1].push_back(i+n);
}
if(ans[0].size()&&ans[1].size()) dsr++;
for(iter i=ans[0].begin();i!=ans[0].end();++i) {
for(iter j=ans[1].begin();j!=ans[1].end();++j) {
if(!mp[*i][*j-n]) ok[*i]++;
}
}
for(iter i=ans[1].begin();i!=ans[1].end();++i) {
for(iter j=ans[0].begin();j!=ans[0].end();++j) {
if(mp[*i-n][*j]) ok[*i]++;
}
}
int siz_0[2]={};
for(int k=0;k<=1;++k)
for(iter i=ans[k].begin();i!=ans[k].end();++i)
if(!ok[*i]) siz_0[k]++;
if(ans[0].size()>1) dsr+=siz_0[0];
if(ans[1].size()>1) dsr+=siz_0[1];
for(iter i=ans[0].begin();i!=ans[0].end();++i) {
if(ok[*i]==1) {
for(iter j=ans[1].begin();j!=ans[1].end();++j) {
if(!mp[*i][*j-n]&&!ok[*j]) dsr++;
}
}
}
for(iter i=ans[1].begin();i!=ans[1].end();++i) {
if(ok[*i]==1) {
for(iter j=ans[0].begin();j!=ans[0].end();++j) {
if(mp[*i-n][*j]&&!ok[*j]) dsr++;
}
}
}
printf("%d\n",dsr);
return 0;
}

# bzoj2215: [Poi2011]Conspiracy 2-sat的更多相关文章

  1. bzoj2215: [Poi2011]Conspiracy

    Description Byteotia的领土被占领了,国王Byteasar正在打算组织秘密抵抗运动.国王需要选一些人来进行这场运动,而这些人被分为两部分:一部分成为同谋者活动在被占领区域,另一部分是 ...

  2. BZOJ2215[Poi2011]Conspiracy——2-SAT+tarjan缩点

    题目描述 Byteotia的领土被占领了,国王Byteasar正在打算组织秘密抵抗运动.国王需要选一些人来进行这场运动,而这些人被分为两部分:一部分成为同谋者活动在被占领区域,另一部分是后勤组织在未被 ...

  3. POI2011题解

    POI2011题解 2214先咕一会... [BZOJ2212][POI2011]Tree Rotations 线段树合并模板题. #include<cstdio> #include< ...

  4. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  5. POI做题笔记

    POI2011 Conspiracy (2-SAT) Description \(n\leq 5000\) Solution 发现可拆点然后使用2-SAT做,由于特殊的关系,可以证明每次只能交换两个集 ...

  6. 「POI2011 R1」Conspiracy

    「POI2011 R1」Conspiracy 解题思路 : 问题转化为,将点集分成两部分,其中一部分恰好组成一个团,其中另一部分恰好组成一个独立集. 观察发现,如果求出了一个解,那么答案最多可以在这个 ...

  7. BZOJ2527: [Poi2011]Meteors

    补一发题解.. 整体二分这个东西,一开始感觉复杂度不是很靠谱的样子 问了po姐姐,说套主定理硬干.. #include<bits/stdc++.h> #define ll long lon ...

  8. 多边形碰撞 -- SAT方法

    检测凸多边形碰撞的一种简单的方法是SAT(Separating Axis Theorem),即分离轴定理. 原理:将多边形投影到一条向量上,看这两个多边形的投影是否重叠.如果不重叠,则认为这两个多边形 ...

  9. BZOJ2276: [Poi2011]Temperature

    2276: [Poi2011]Temperature Time Limit: 20 Sec  Memory Limit: 32 MBSubmit: 293  Solved: 117[Submit][S ...

随机推荐

  1. Unity shader学习之Forward Rendering Path

    Forward rendering path shader如下: // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObje ...

  2. Unity之fragment shader中如何获得视口空间中的坐标

    2种方法: 1. 使用 VPOS 或 WPOS语义,如: Shader "Test/ScreenPos1" { SubShader { Pass { CGPROGRAM #prag ...

  3. kali linux主题下载

    主题下载网站 https://www.gnome-look.org/ 下载好安装包后解压 将文件夹移动到 usr/share/theme/ 下 mv download ../usr/share/the ...

  4. html5-css边框全

    /*div{    width: 500px;    height: 300px;    background: rgb(122,30,60);    border: 10px solid black ...

  5. Redhat 简单本地yum 配置

    Redhat 简单本地yum 配置 一.将redhat 系统的镜像挂载到系统上 Vmware Workstion 环境下: [虚拟机设置]--[硬件]--[CD/DVD]--[使用ISO映像文件]-- ...

  6. flask框架----上下文管理

    一.上下文管理相关知识点: a.类似于本地线程 创建Local类: { 线程或协程唯一标识: { 'stack':[request],'xxx':[session,] }, 线程或协程唯一标识: { ...

  7. Linux 执行程序 报错误:Permission denied.

    是对此文件所在位置没有权限导致的 chmod +x /home/yourfile 即可

  8. String类型转json 转JSONObject 转 JSONArray 以及 遍历

    public PageVo getByPage(int pageNum, int pageSize) { PageVo pageVo = new PageVo(); System.out.printl ...

  9. Makefile依赖关系中的竖线“|”

    网上搜索无果,于是自己查看了一下makefile的info文件,其中解释如下: [java] view plain copy print? target : prerequisites   [TAB] ...

  10. PyCharm‘s Project Deployment

    当在本地写完项目,部署到服务器上调试的时候,难免会碰到代码的修修改改,但由于项目在服务器上,修改起来相对麻烦.各路大神或许有自己的方法去解决.这篇博客演示利用PyCharm的Deployment功能, ...