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. HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhereVisitor

    看到的最长的类名: HasThisTypePatternTriedToSneakInSomeGenericOrParameterizedTypePatternMatchingStuffAnywhere ...

  2. Linux基础命令---apwatch

    arpwatch      arpwatch指令可以监听网络设备和ip地址的对应关系,将发现的信息发送到系统日志“/var/log/message”. 此命令的适用范围:RedHat.RHEL.Ubu ...

  3. sql之left join、right join、inner join的区别,连接自己时的查询结果测试

    sql之left join.right join.inner join的区别 left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括 ...

  4. URL some

    ** 路由系统:URL配置(URLconf)就像Django所支撑网站的目录. 本质是URL与该URL要调用的函数的映射表 基本格式 : from django.conf.urls import ur ...

  5. 算法提高 c++_ch02_01 (强制类型转换)

    编写一个程序,利用强制类型转换打印元音字母大小写10种形式的ASCII码. 输出的顺序为:大写的字母A,E,I,O,U的ASCII码,小写的字母a,e,i,o,u的ASCII码.所有的ASCII码都用 ...

  6. 如何给webview页面自定义404页面

    //示例地图类 package com.can2do.doimobile.news; import android.os.Bundle; import android.os.Handler; impo ...

  7. GoldenGate for bigdata 12.3.1.1

    GoldenGate for big data 12.3.1.1在8.18已经发布,主要新特性如下: 1. 新目标:Amazon Kinesis 2. 新目标:使用Kafka Connect API及 ...

  8. Python进阶【第十篇】模块(上)

    ·一.模块 模块就是一组功能的集合体,我们的程序可以导入模块来复用模块里的功能.为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这 ...

  9. 删去k个数字后的最小值

    public static String removeKDigits(String num,int k) { //新整数的最终长度=原长度 - k int newLength=num.length() ...

  10. django框架基本介绍

    一.mvc和mtv 1.mvc介绍 MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model).视图(View)和控制器( ...