题意

给出n个点的一个图,要求把所有点分成两部分,一部分是一个团,一部分是一个独立集.n<=5000

分析

记录自己的愚蠢...
首先考虑如何判断存在可行方案,那么每个点要么属于团,要么属于独立集,且可以根据一个点属于哪一部分推出其他某些属于哪一部分.(如果我们钦定点A属于团,那么所有和A没有连边的点都必须属于独立集,如果我们钦定点A属于独立集,那么所有和A有连边的点都必须属于团).这样的二元关系相互推导的模型自然可以转化为2-SAT.点数5000,边数5000*5000,所以需要线性的做法,跑tarjan强联通分量.
然后我就不会怎么统计方案了,愚蠢*1
看题解,发现有个很妙的性质:假如我们有两个不同的方案都是合法的,那么不可能存在两个不同的点u,v使得这两个点在一个方案中都在独立集里,在另一个方案中都在团里.正确性是显然的,然而没有想到.这个结论虽然简单却非常有力:只需要找出任意一个可行解,那么其他可行解都可以由这个可行解进行次数不多的修改得到.(有三种情况:把独立集中的一个点拿到团里;把团里的一个点拿到独立集里;把团里的一个点和独立集里的一个点互换),那么我们枚举所有可能的修改情况即可.
然后我就把tarjan求强连通分量写错了.把x出栈后,我把in_stack[x]赋值为true...(应当赋值为false).愚蠢*2
过了样例交一发,然后WA了.愚蠢*3
发现有个if里的判断条件少加了一个!,意思全反了.改过来交,又WA了.愚蠢*4
发现我求出来的方案不一定两个集合都非空.改过来交,又WA了.愚蠢*5
发现我默认2SAT求出来的初始解两个集合都非空.改过来交,终于A了.
这做题状态不行啊...

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn=10005,maxm=25000005;
struct edge{int to,next;
}lst[maxm],lst2[maxm];int len=1,first[maxn],len2=1,first2[maxn];
void addedge(int a,int b){lst[len].to=b;lst[len].next=first[a];first[a]=len++;
}
void addedge2(int a,int b){lst2[len2].to=b;lst2[len2].next=first2[a];first2[a]=len2++;
}
int conv(int a,int t){return (a<<1)|t;
}//conv(a,1):a is spy conv(a,0):a is supply
int n;
bool E[maxn][maxn];
int dfn[maxn],T,stk[maxn],top,low[maxn],belong[maxn],tot;
bool ins[maxn];
vector<int> scc[maxn];
void dfs(int x){dfn[x]=low[x]=++T;ins[stk[top++]=x]=true;for(int pt=first[x];pt;pt=lst[pt].next){if(!dfn[lst[pt].to]){dfs(lst[pt].to);if(low[lst[pt].to]<low[x])low[x]=low[lst[pt].to];}else if(ins[lst[pt].to]&&dfn[lst[pt].to]<low[x])low[x]=dfn[lst[pt].to];}if(dfn[x]==low[x]){++tot;do{ins[stk[--top]]=false;belong[stk[top]]=tot;scc[tot].push_back(stk[top]);}while(stk[top]!=x);}
}
bool twosat(){for(int i=2;i<=2*n+1;++i){if(!dfn[i])dfs(i);}for(int i=1;i<=n;++i){if(belong[conv(i,0)]==belong[conv(i,1)])return false;}return true;
}
int col[maxn],scccol[maxn];
bool mark[maxn];
bool toposorted[maxn];
int seq[maxn],cnt;
void toposort(int x){if(toposorted[x])return;for(int pt=first2[x];pt;pt=lst2[pt].next){toposort(lst2[pt].to);}seq[++cnt]=x;toposorted[x]=true;
}
void getsol(){for(int i=2;i<=2*n+1;++i){for(int pt=first[i];pt;pt=lst[pt].next){if(belong[i]!=belong[lst[pt].to]){addedge2(belong[i],belong[lst[pt].to]);}}}for(int i=1;i<=tot;++i)toposort(i);for(int i=1;i<=tot;++i){int x=seq[i];if(mark[x]&&scccol[x]==0)continue;mark[x]=true;scccol[x]=1;for(vector<int>::iterator pt=scc[x].begin();pt!=scc[x].end();++pt){mark[belong[(*pt)^1]]=true;scccol[belong[(*pt)^1]]=0;}}
}
int cnt_anti[maxn],anti[maxn];
int main(){scanf("%d",&n);for(int i=1,num,x;i<=n;++i){scanf("%d",&num);while(num--){scanf("%d",&x);E[i][x]=true;}}for(int i=1;i<=n;++i){for(int j=i+1;j<=n;++j){if(E[i][j]){addedge(conv(i,1),conv(j,0));addedge(conv(j,1),conv(i,0));}else{addedge(conv(i,0),conv(j,1));addedge(conv(j,0),conv(i,1));}}}if(!twosat())printf("0\n");else{getsol();for(int i=1;i<=n;++i)col[i]=scccol[belong[conv(i,1)]];//for(int i=1;i<=n;++i)printf("%d",col[i]);for(int i=1;i<=n;++i){if(!col[i]){for(int j=1;j<=n;++j){if(col[j]&&E[i][j]){anti[i]=j;cnt_anti[i]++;}}}else{for(int j=1;j<=n;++j){if((!col[j])&&(!E[i][j])){anti[i]=j;cnt_anti[i]++;}}}}int num[2]={0,0};for(int i=1;i<=n;++i)num[col[i]]++;int ans=(num[0]!=0&&num[1]!=0);for(int i=1;i<=n;++i){if(cnt_anti[i]==0&&num[col[i]]!=1)ans++;}for(int i=1;i<=n;++i){for(int j=1;j<=n;++j){if(col[i]&&(!col[j])){if(cnt_anti[i]==0||(cnt_anti[i]==1&&anti[i]==j)){if(cnt_anti[j]==0||(cnt_anti[j]==1&&anti[j]==i))ans++;}}}}printf("%d\n",ans);}return 0;
}

转载于:https://www.cnblogs.com/liu-runda/p/7157738.html

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\).可以将分到团和独立集中分别看为0和1. 如果两个点之间 ...

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

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

  4. bzoj2215: [Poi2011]Conspiracy

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2215 思路:一道很好的2-sat题 首先一个人要么分配给同谋者,要么分配给后勤组织 这可以考 ...

  5. BZOJ2215 : [Poi2011]Conspiracy

    考虑构造一组可行解,把每个点拆成两个点x0,x1,x0表示后勤组织,x1表示同谋者. 若x与y认识,则x1向y0连边. 若x与y不认识,则x0向y1连边. 如此求出一组2-SAT的可行解,如果无解则答 ...

  6. 「POI2011 R1」Conspiracy

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

  7. [bzoj2527][Poi2011]Meteors_整体二分_树状数组

    Meteors bzoj-2527 Poi-2011 题目大意:题目链接. 注释:略. 想法: 首先答案可以离线,且具有单调性. 这里的单调性就是随着时间的推移,每个国家收集的陨石数增加. 不难想到整 ...

  8. [bzoj2213][Poi2011]Difference_动态规划

    Difference bzoj-2213 Poi-2011 题目大意:已知一个长度为n的由小写字母组成的字符串,求其中连续的一段,满足该段中出现最多的字母出现的个数减去该段中出现最少的字母出现的个数最 ...

  9. 洛谷 P3521 [POI2011]ROT-Tree Rotations 解题报告

    P3521 [POI2011]ROT-Tree Rotations 题意:递归给出给一棵\(n(1≤n≤200000)\)个叶子的二叉树,可以交换每个点的左右子树,要求前序遍历叶子的逆序对最少. 大体 ...

最新文章

  1. 病毒入侵计算机的危害,那些年电脑中过的病毒,中病毒的危害又有哪些
  2. 0513JS基础:数组内置方法、数学函数、时间函数
  3. 合同模板布局html,套打模板制作(合同类模板)
  4. 访问图像中每个像素的值
  5. C++打印STAIRS 图案算法(附完整源码)
  6. mysql手工注入——盲注
  7. java json帮助类_java 写一个JSON解析的工具类
  8. linux tcp连接计算机,计算机基础知识——linux socket套接字tcp连接分析
  9. ELK日志系统之使用Rsyslog快速方便的收集Nginx日志
  10. 【报告分享】2019年12月郭广昌混沌课程ppt(附下载链接)
  11. javascript操作listbox方法 【转】
  12. 3DMine安装教程(附详细图文安装步骤)
  13. 如何提高服务器硬盘读写速度,如何加速硬盘读写速度,如何完全控制ntfs 分区...
  14. 20221115使用google文档翻译SRT格式的字幕
  15. chrome导入\导出登录密码
  16. HDU-3374 String Problem
  17. **传统线上支付 区块链**
  18. java 替换指定位置的字符_java Sting 如何替换指定位置的 字符?
  19. 曾谨言量子力学教程第3版笔记和课后答案
  20. robotframework 内置库BuiltIn学习笔记

热门文章

  1. pytest-pytest.main()运行测试用例,pytest参数
  2. CRM的客户数据模型:Siebel Party Data Model (VI)
  3. 《乔布斯传》英文原著重点词汇笔记(十四)【 chapter thirteen】
  4. 利用 Python 爬取了近 3000 条单身女生的数据,究竟她们理想的择偶标准是什么?
  5. 收好这份武林秘籍,让你分库分表再无烦恼
  6. 初学者如何学好Java
  7. 计算机桌面怎么能添加文字,怎么在电脑桌面上添加文字
  8. 计算机教室英语怎么读音,网络教室,network classroom,音标,读音,翻译,英文例句,英语词典...
  9. 小汪汪服务器不稳定,小汪汪闪退了怎么办 小汪汪闪退问题解决办法
  10. 电信云堤·抗D(电信云堤清洗高防服务器)提供超强T级DDoS处理能力