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

4
2 2 3
2 1 3
3 1 2 4
1 3

Sample Output

3

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的更多相关文章

  1. # bzoj2215: [Poi2011]Conspiracy 2-sat

    bzoj2215: [Poi2011]Conspiracy 2-sat 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2215 思路 一个点的 ...

  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. BZOJ2276: [Poi2011]Temperature

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

  9. BZOJ2213: [Poi2011]Difference

    2213: [Poi2011]Difference Time Limit: 10 Sec  Memory Limit: 32 MBSubmit: 343  Solved: 108[Submit][St ...

随机推荐

  1. 406. Queue Reconstruction by Height

    一开始backtrack,设计了很多剪枝情况,还是TLE了 ..后来用PQ做的. 其实上面DFS做到一半的时候意识到应该用PQ做,但是不确定会不会TLE,就继续了,然后果然TLE了.. PQ的做法和剪 ...

  2. Maven学习系列二(1-5)

    Maven学习系列二(1-5) 本文转自 QuantSeven 博客,讲解精炼易懂,适合入门,链接及截图如下 http://www.cnblogs.com/quanyongan/category/47 ...

  3. TCP洪水攻击(SYN Flood)的诊断和处理

    TCP洪水攻击(SYN Flood)的诊断和处理   SYN Flood介绍 前段时间网站被攻击多次,其中最猛烈的就是TCP洪水攻击,即SYN Flood. SYN Flood是当前最流行的DoS(拒 ...

  4. linux mysql命令

    一: 1.启动 MySQL安装完成后启动文件mysql在/etc/init.d目录下,在需要启动时运行下面命令即可. /etc/init.d/mysql start 2.停止 /usr/bin/mys ...

  5. js鼠标事件

    今天遇到一个非常奇怪而又搞笑的事情:给一个a标签添加一个鼠标移动上时给一个事件,我给其添加的是一个onMouseMove事件,结果在IE6 7 8 9和GOOLE中都很正常,结果在Firox中出现问题 ...

  6. Elasticsearch .Net Client NEST 索引DataSet数据

    NEST 索引DataSet数据,先序列化然后转成dynamic 类型进行索引: /// <summary> /// 索引dataset /// </summary> /// ...

  7. C++链表与键值对

    <算法>一书中,在算法3.1中提到了Map的实现,这里根据书上的思想,用单向链表简单写了写. #ifndef SEQUENTIAL_H #define SEQUENTIAL_H templ ...

  8. Initializer block.

    Ref: Initializing Fields Instance initializers are permitted to refer to the current object via the ...

  9. Hash - a javascript dictionary object.

    Hash,in wikipedia, may relevant to many stuffs. In javascript, hash is a group of name/value pairs w ...

  10. ASP.NET 导入EXCEL文档

    鉴于教务一般都是手动输入学生信息,在未了解本校数据库的客观情况之下,我们准备设计一个导入excel文档中学生信息如数据库的功能.结合网上各类大牛的综合版本出炉.. 首先具体的实现思想如下: 1.先使用 ...