bzoj2215: [Poi2011]Conspiracy
Description
Byteotia的领土被占领了,国王Byteasar正在打算组织秘密抵抗运动。国王需要选一些人来进行这场运动,而这些人被分为两部分:一部分成为同谋者活动在被占领区域,另一部分是后勤组织在未被占领的领土上运转。但是这里出现了一个问题: 1. 后勤组织里的任意两人都必须是熟人,以促进合作和提高工作效率。 2. 同谋者的团体中任意两人都不能是熟人。 3. 每一部分都至少要有一个人。国王想知道有多少种分配方案满足以上条件,当然也有可能不存在合理方案。现在国王将这个问题交由你来解决!
Input
第一行一个整数n(2<=n<=5000)表示有n个人参与该抵抗运动,标号为1..n。 之后有n行,第i行的第一个数ki(0<=ki<=n-1)表示i认识ki个人,随后的ki个数表示i的熟人。 p.s.输入满足:如果i是x的熟人,x会在i的序列中出现同时i也会出现在x的熟人序列中。
Output
符合条件的方案总数。
Sample Input
2 2 3
2 1 3
3 1 2 4
1 3
Sample Output
HINT
Hint 1和4分到同谋者组织,2和3为后勤组织。 2和4分到同谋者组织,1和3为后勤组织。 4单独分到同谋者组织,1和2、3为后勤组织。
题解:
考虑构造一组可行解,把每个点拆成两个点x0,x1,x0表示后勤组织,x1表示同谋者。
若x与y认识,则x1向y0连边。
若x与y不认识,则x0向y1连边。
如此求出一组2-SAT的可行解,如果无解则答案为0。
若有解,那么最多只能把一个人从后勤组织改为同谋者,也最多只能把一个人从同谋者改为后勤组织,也可以将一个在同谋者另一个在后勤组织的两个人交换。
显然不能直接暴力搞
先预处理出每个点和它相冲突的点的个数和其中任意一个冲突点的编号
冲突点定义为假如把这个点放到对面去,对面的点中会和这个点发生冲突的点
举个例子,假如两个人u和v,u在后勤,v在同谋者,而u,v互相认识,则v是u的矛盾点
或者是两个人a和b,a在同谋者,b在后勤,而a,b不认识,这b是a的矛盾点
先讨论要交换的情况
显然,当一个点的矛盾点数量超过2,他既不能直接去对面,也不能和对面的某个人直接交换
当一个点u的矛盾点为1时,设它的矛盾点为v
假如v也只有一个矛盾点,且v的矛盾点是u,显然这两人可以交换(注意不要重复计算)
假如v没有矛盾点,显然可以直接交换
设在后勤组织中没有矛盾点的个数为t0,同谋者中没有矛盾点的个数为t1,显然这两类点可以任取一对来交换,方案数为t0*t1
再讨论直接去对面的情况
假如这个点没有矛盾点且他所在的组织超过1人(要保证每一边至少有一人),则他可以去对面
然后初始解假如每一边都至少有一人,那么这也是一个合法方案
code:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 5005
using namespace std;
char ch;
bool ok;
void read(int &x){
for (ok=,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=;
for (x=;isdigit(ch);x=x*+ch-'',ch=getchar());
if (ok) x=-x;
}
int n,k,x,con[maxn],cnt0,cnt1,list0[maxn],list1[maxn],num[maxn],boom[maxn];
bool g[maxn][maxn],bo[maxn];
struct Graph{
int tot,now[maxn<<],son[maxn*maxn],pre[maxn*maxn];
int idx,dfn[maxn<<],low[maxn<<],top,stack[maxn],cnt,bel[maxn<<];
bool in[maxn<<];
void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;}
void dfs(int u){
dfn[u]=low[u]=++idx,stack[++top]=u,in[u]=;
for (int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if (!dfn[v]) dfs(v),low[u]=min(low[u],low[v]);
else if (in[v]) low[u]=min(low[u],dfn[v]);
if (dfn[u]==low[u]){
int v; ++cnt;
do{v=stack[top--],in[v]=,bel[v]=cnt;}while (v!=u);
}
}
}G;
int main(){
read(n);
for (int i=;i<=n;i++){
read(k),con[i]=k;
while (k--) read(x),g[i][x]=;
}
for (int i=;i<=n;i++) for (int j=;j<=n;j++) if (i!=j){
if (g[i][j]) G.put((i<<)+,j<<); else G.put(i<<,(j<<)+);
}
for (int i=;i<=(n<<)+;i++) if (!G.dfn[i]) G.dfs(i);
for (int i=;i<=n;i++){
if (G.bel[i<<]==G.bel[(i<<)+]){puts("");return ;}
if (G.bel[i<<]<G.bel[(i<<)+]) list0[++cnt0]=i;
else bo[i]=,list1[++cnt1]=i;
}
int ans=(cnt0&&cnt1);
for (int i=;i<=cnt0;i++) for (int j=;j<=cnt1;j++)
if (g[list0[i]][list1[j]]) num[list0[i]]++,boom[list0[i]]=list1[j];
for (int i=;i<=cnt1;i++) for (int j=;j<=cnt0;j++)
if (!g[list1[i]][list0[j]]) num[list1[i]]++,boom[list1[i]]=list0[j];
for (int i=;i<=n;i++) if (num[i]==){
if (num[boom[i]]==&&boom[i]>i&&boom[boom[i]]==i) ans++;
else if (!num[boom[i]]) ans++;
}
int t0=,t1=;
for (int i=;i<=n;i++) if (!num[i]){
if ((bo[i]&&cnt1>)||(!bo[i]&&cnt0>)) ans++;
if (bo[i]) t1++; else t0++;
}
ans+=t1*t0;
printf("%d\n",ans);
return ;
}
bzoj2215: [Poi2011]Conspiracy的更多相关文章
- # bzoj2215: [Poi2011]Conspiracy 2-sat
bzoj2215: [Poi2011]Conspiracy 2-sat 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2215 思路 一个点的 ...
- BZOJ2215[Poi2011]Conspiracy——2-SAT+tarjan缩点
题目描述 Byteotia的领土被占领了,国王Byteasar正在打算组织秘密抵抗运动.国王需要选一些人来进行这场运动,而这些人被分为两部分:一部分成为同谋者活动在被占领区域,另一部分是后勤组织在未被 ...
- POI2011题解
POI2011题解 2214先咕一会... [BZOJ2212][POI2011]Tree Rotations 线段树合并模板题. #include<cstdio> #include< ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- POI做题笔记
POI2011 Conspiracy (2-SAT) Description \(n\leq 5000\) Solution 发现可拆点然后使用2-SAT做,由于特殊的关系,可以证明每次只能交换两个集 ...
- 「POI2011 R1」Conspiracy
「POI2011 R1」Conspiracy 解题思路 : 问题转化为,将点集分成两部分,其中一部分恰好组成一个团,其中另一部分恰好组成一个独立集. 观察发现,如果求出了一个解,那么答案最多可以在这个 ...
- BZOJ2527: [Poi2011]Meteors
补一发题解.. 整体二分这个东西,一开始感觉复杂度不是很靠谱的样子 问了po姐姐,说套主定理硬干.. #include<bits/stdc++.h> #define ll long lon ...
- BZOJ2276: [Poi2011]Temperature
2276: [Poi2011]Temperature Time Limit: 20 Sec Memory Limit: 32 MBSubmit: 293 Solved: 117[Submit][S ...
- BZOJ2213: [Poi2011]Difference
2213: [Poi2011]Difference Time Limit: 10 Sec Memory Limit: 32 MBSubmit: 343 Solved: 108[Submit][St ...
随机推荐
- 【设计模式 - 1】之工厂模式(Factory)
1 模式简介 1.1 工厂模式作用 工厂模式解决的是"使用new关键字获取对象造成松耦合"的问题. 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏 ...
- Matrix的set,pre,post调用顺序
Matrix调用一系列set,pre,post方法时,可视为将这些方法插入到一个队列.当然,按照队列中从头至尾的顺序调用执行.其中pre表示在队头插入一个方法,post表示在队尾插入一个方法.而set ...
- todoing
1.如果系类没有数据需要返回么? 2.需要增加系列的门店打点么?
- 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(36)-文章发布系统③-kindeditor使用
原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(36)-文章发布系统③-kindeditor使用 我相信目前国内富文本编辑器中KindEditor 属于前 ...
- javascript中的稀疏数组(sparse array)和密集数组
学习underscore.js数组相关API的时候.遇到了sparse array这个东西,曾经没有接触过. 这里学习下什么是稀疏数组和密集数组. 什么是密集数组呢?在java和C语言中,数组是一片连 ...
- 基于NPOI开源框架写的ExcelHelper【转载】
namespace ExcelTest { using System; using System.Collections.Generic; using System.Data; using Syste ...
- 给考研计划报考“管理学科学与project”方向大学生的建议(大二阶段)
[来信]丁老师: 你好.在做学习计划前能了解到PDCA循环,着实感到受益匪浅. 这一理念不仅适用于质量管理体系.也适用于一切循序渐进的管理工作. 了解PDCA循环后.对此次学习计划的制定起到一定的导向 ...
- linux innode图解2
http://www.opsers.org/linux-home/base/the-knowledge-that-one-day-learn-linux-file-system.html 文件系统是操 ...
- Qt 学习之路 :信号槽
信号槽是 Qt 框架引以为豪的机制之一.熟练使用和理解信号槽,能够设计出解耦的非常漂亮的程序,有利于增强我们的技术设计能力. 所谓信号槽,实际就是观察者模式.当某个事件发生之后,比如,按钮检测到自己被 ...
- 表达式:使用API创建表达式树(5)
一.ConditionalExpression:表达式 生成如 IIF((a == b), "a和b相等", "a与b不相等") 式子. 使用: Paramet ...