LOJ#2155. 「POI2011 R1」同谋者 Conspiracy
题目描述
题解:
这个题目要求的是把一张无向图变成一个团和一个独立集的方案数。这看似好像无从下手。那么我们可以换一个角度思考,我们考虑先求出一个解,然后通过调整得出所有解。
假设已经求出了一个解,我们会发现,其它所有的解只可能由这个解通过三种方式得到:
1.将一个原本在独立集里面的点放到团中(可行的条件下)。
2.将一个原本在团中的点放到独立集中(可行的条件下)。
3.将一个独立集中的点和团中的点交换(可行的条件下)。
意思就是,如果有属于同一组中的两个及以上的点到另一个组中,就肯定不行。
那么接下来问题就转化成了怎样求一组解。我们可以把一个点拆分成两个状态,放入团或是放入独立集中。那么我们的目标即是将这2n个状态分到两个集合中,每个集合中有n个状态,此时我们随便选择一个集合,就是一组可行解了。
那么我们就可以用2-Sat来解决。
约束条件是如果a到b有边,那么a在独立集中,b就不能在。
如果a到b无边,那么a在团中,b就不能在。
剩下的过程就是Tarjan缩点加上建反图拓扑排序一下。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=10005;
int n;
namespace twosat{vector<int> e[maxn],a[maxn],f[maxn];bool vis[maxn];bitset<5005> hsh[5005];int tot,top,ans,inn[maxn],c[maxn],dfn[maxn],low[maxn],gr[maxn],stack[maxn],que[maxn];bool pic[maxn],pd[maxn],pd1[maxn];void nosolu(){printf("0\n"); exit(0);}void init(){scanf("%d",&n);for (int i=1;i<=n;i++){int x,y; scanf("%d",&x);for (int j=1;j<=x;j++) scanf("%d",&y),hsh[i][y]=1;for (int j=1;j<=n;j++)if (j!=i){if (hsh[i][j]) e[2*i].push_back(2*j-1);//2*i-1是团,2×i是独立集else e[2*i-1].push_back(2*j); }}if (n==2) {printf("2\n"); exit(0);}}void tarjan(int x){dfn[x]=low[x]=++tot,vis[x]=1,stack[++top]=x;for (int j=0;j<e[x].size();j++)if (!dfn[e[x][j]]) {int y=e[x][j];tarjan(y);low[x]=min(low[x],low[y]);} else if (vis[e[x][j]]) low[x]=min(low[x],dfn[e[x][j]]);if (low[x]==dfn[x]){while (stack[top]!=x) {gr[stack[top]]=x,vis[stack[top]]=0,top--;}gr[stack[top]]=x,vis[stack[top]]=0,top--;}}void tar(){for (int i=1;i<=2*n;i++) if (!dfn[i]) tarjan(i);}int get(int x){if (x%2==1) return x+1; else return x-1;}void rebuild(){for (int i=1;i<=2*n;i++) f[gr[i]].push_back(i);for (int i=1;i<=n;i++) if (gr[2*i-1]==gr[2*i]) nosolu();for (int i=1;i<=2*n;i++){for (int j=0;j<e[i].size();j++)if (gr[i]!=gr[e[i][j]]) a[gr[e[i][j]]].push_back(gr[i]),inn[gr[i]]++; e[i].clear();}}void topsort(){memset(vis,0,sizeof(vis));int head=0,tail=0;for (int i=1;i<=2*n;i++)if (!inn[i]) que[++tail]=i;while (head!=tail){head++; int u=que[head];for (int i=0;i<f[u].size();i++)if (!vis[get(f[u][i])]) pic[f[u][i]]=1,vis[f[u][i]]=1;f[u].clear();for (int i=0;i<a[u].size();i++)if (inn[a[u][i]]){int v=a[u][i]; inn[v]--;if (!inn[v]) que[++tail]=v;}a[u].clear();}}void calc(){int ans=0,sum1=0,sum2=0;for (int i=1;i<=n;i++)if (pic[2*i-1]) c[i]=1,sum1++; else c[i]=2,sum2++; //1是团,2是独立集if (sum1&&sum2) ans++;for (int i=1;i<=n;i++)if (c[i]==1){bool check=0;for (int j=1;j<=n;j++)if (hsh[i][j]&&c[j]==2) {check=1; break;}if (check==0&&(sum1-1)) ans++,pd[i]=1;} else {bool check=0;for (int j=1;j<=n;j++)if (c[j]==1&&(!hsh[i][j])) {check=1; break;}if (check==0&&(sum2-1)) ans++,pd1[i]=1;}for (int i=1;i<n;i++)for (int j=i+1;j<=n;j++)if (((pd[i]&&pd1[j])||(pd1[i]&&pd[j]))&&hsh[i][j])ans++;printf("%d\n",ans);}void solve(){init(); tar(); rebuild(); topsort(); calc();}
}
int main(){twosat::solve();return 0;
}
LOJ#2155. 「POI2011 R1」同谋者 Conspiracy相关推荐
- 「POI2011 R1」Conspiracy
「POI2011 R1」Conspiracy 解题思路 : 问题转化为,将点集分成两部分,其中一部分恰好组成一个团,其中另一部分恰好组成一个独立集. 观察发现,如果求出了一个解,那么答案最多可以在这个 ...
- Loj #3124. 「CTS2019 | CTSC2019」氪金手游
Loj #3124. 「CTS2019 | CTSC2019」氪金手游 题目描述 小刘同学是一个喜欢氪金手游的男孩子. 他最近迷上了一个新游戏,游戏的内容就是不断地抽卡.现在已知: - 卡池里总共有 ...
- LOJ#3054. 「HNOI 2019」鱼
LOJ#3054. 「HNOI 2019」鱼 https://loj.ac/problem/3054 题意 平面上有n个点,问能组成几个六个点的鱼.(n<=1000) 分析 鱼题,劲啊. 容易想 ...
- LOJ 2288「THUWC 2017」大葱的神力
LOJ 2288「THUWC 2017」大葱的神力 Link Solution 比较水的提交答案题了吧 第一个点爆搜 第二个点爆搜+剪枝,我的剪枝就是先算出 \(mx[i]\) 表示选取第 \(i \ ...
- loj #2509. 「AHOI / HNOI2018」排列
#2509. 「AHOI / HNOI2018」排列 题目描述 给定 nnn 个整数 a1,a2,-,an(0≤ai≤n),以及 nnn 个整数 w1,w2,-,wn.称 a1,a2,-,an 的一个 ...
- LOJ 2979 「THUSCH 2017」换桌——多路增广费用流
题目:https://loj.ac/problem/2979 原来的思路: 优化连边.一看就是同一个桌子相邻座位之间连边.相邻桌子对应座位之间连边. 每个座位向它所属的桌子连边.然后每个人建一个点,向 ...
- LOJ 3124 「CTS2019 | CTSC2019」氪金手游——概率+树形DP
题目:https://loj.ac/problem/3124 看了题解:https://www.cnblogs.com/Itst/p/10883880.html 先考虑外向树. 考虑分母是 \( \s ...
- loj #3086. 「GXOI / GZOI2019」逼死强迫症
背景: 好像也没什么. 题目传送门: https://loj.ac/problem/3086 题意: 给一个2∗n2*n2∗n的矩阵,现在要用2∗(n−1)2*(n-1)2∗(n−1)的矩形和222块 ...
- LOJ #6672. 「XXOI 2019」惠和惠惠和惠惠惠(生成函数,整式递推)
题目 没有latex就没有推式子的动力怎么破? 设 f i , j f_{i,j} fi,j表示在前 j j j个回合里,血量为 0 0 0了 i i i个回合且第 j j j个回合血量为 0 0 ...
- LOJ#3085. 「GXOI / GZOI2019」特技飞行(KDtree+坐标系变换)
题面 传送门 前置芝士 请确定您会曼哈顿距离和切比雪夫距离之间的转换,以及\(KDtree\)对切比雪夫距离的操作 题解 我们发现\(AB\)和\(C\)没有任何关系,所以关于\(C\)可以直接暴力数 ...
最新文章
- 深度丨Google告诉你为什么各大机构都在争相研究AI芯片
- html select滚动轴,javascript - html select scroll bar - Stack Overflow
- 解决AJAX CalendarExtender控件不显示中文的情况(转帖博客园某人(不好意思,实在是没有找到您的尊姓大名,感谢一下!))...
- 《深入理解java内存模型》学习整理1
- 华为OJ: 公共字符串计算
- php声明一个类的关键字,php中怎么实例化一个类
- oracle 数组的用法,oracle存储过程中数组的使用
- centos mysql 允许远程访问
- mysql 查看数据库字段是否存在,mysql查询某张表是否存在某个字段和判断是否存在某个表名...
- 微信开发 调用摄像机拍照(录像)功能
- XP开通局域网共享(访问本机无需验证即可进入)
- mysql 事务处理null_如何使用Mysql正确的处理财务数据
- BZOJ4597 SHOI2016随机序列(线段树)
- k2ttl救砖_拆解刷breed变砖的斐讯K2P并修复
- 联想ThinkPad E15 2021款 酷睿版怎么样?测评值得买吗?
- 由公司APP大面积闪退问题引发的测试基建思考
- 学校计算机教室学生使用记录表,学校学生信息技术教学计划
- TCL发布两款可穿戴设备;中兴通讯推出第三代5G室内路由器;绘王联合制作《河岸》获棕榈泉国际短片电影节最佳动画奖 | 全球TMT...
- 面试前端的简历的注意事项
- vue 项目node服务器部署流程