传送门

解题思路

  \(orz\)出题人的神仙做法。本蒟蒻看不懂,就水个求补图再二分图染色的方法来\(%1%\)出题人。

  

  首先我们对图中\(m\)个关系连边,发现这样是没法做的,因为我们最后要关注的是谁和谁不能在一起,这个限制是比较大的。所以我们考虑建一个补图,就是把原来没有的边加边,原来存在的边断掉。这样\(a\)和\(b\)之间有边就代表\(a\)与\(b\)不能属于一个集合,这样就可能形成了若干个图。首先考虑判合法,因为一共只有两个集合,而每个人都必须放到集合里,关系还可以抽象成一张无向图,自然可以想到二分图染色了。我们只需要遍历每一个联通块,然后进行黑白染色判是否合法,只要有一个联通块不合法,那么也就\(GG\)了。

  然后考虑算答案,判完合法之后,我们就可以知道一个了联通块中黑色和白色的不能属于一个集合,剩下的可以任意搭配,所以做一个背包就行了,把每个联通块黑色白色的个数记下来。设\(f[i]\)表示一个集合有\(i\)个人是否成立,转移的时候就模仿\(0/1\)背包,就是看每一个联通块是选黑色进去还是选白色进去。做完背包后一个人数合法仅当\(f[i]=f[n-i]=true\)。这样第一问和第二问的答案就统计出来了,对于第三问的答案,然后\(n^2\)枚举一下每对,如果两个人属于同一个联通块但颜色不相同,并且两个人在补图里没边,就使\(ans3++\),这个也比较好理解,具体实现看代码。

  

  打波广告

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath> using namespace std;
const int MAXN = 2505;
const int MOD = 1e9+7;
typedef long long LL; inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
} int n,m,a[MAXN][MAXN],tot,num,cnt1,cnt2,ans1,ans2,ans3;
int w[MAXN][2],f[MAXN],now[MAXN],col[MAXN],Min;
bool flag; void dfs(int x,int c){
col[x]=c;now[++tot]=x;if(c==1) cnt1++;else cnt2++;
for(int i=1;i<=n;i++)
if(a[i][x]){
if(col[i]==col[x]) {flag=1;return;}
if(!col[i]) dfs(i,3-c);
}
} inline int fast_pow(int x,int y){
int ret=1;
for(;y;y>>=1){
if(y&1) ret=(LL)ret*x%MOD;
x=(LL)x*x%MOD;
}
return ret;
} int main(){
int x,y;n=rd(),m=rd();
for(int i=1;i<=m;i++){
x=rd(),y=rd();
a[x][y]=a[y][x]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j) a[i][j]^=1;
for(int i=1;i<=n;i++) if(!col[i]){
cnt1=cnt2=tot=0;memset(now,0,sizeof(now));
dfs(i,1);if(flag) break;
for(int j=1;j<=tot;j++)
for(int k=j+1;k<=tot;k++)
if(col[now[j]]!=col[now[k]] && !a[now[j]][now[k]]) ans3++;
w[++num][0]=cnt1;w[num][1]=cnt2;
}f[0]=1;
for(int i=1;i<=num;i++){
Min=min(w[i][0],w[i][1]);
for(int j=n;j>=Min;j--){
if(j>=w[i][0]) f[j]|=f[j-w[i][0]];
if(j>=w[i][1]) f[j]|=f[j-w[i][1]];
}
}
for(int i=0;i<=n/2;i++){
if(!f[i] || !f[n-i]) continue;
ans1++;ans2=i;
}
if(flag) puts("-1"),ans3=m; //注意一下这里,如果没有方案的话自然$m$对可以合作的人都无法在一个集合里
else printf("%d %d\n",ans1,(fast_pow(2,n-ans2)-fast_pow(2,ans2)+MOD)%MOD);
printf("%d\n",ans3);
return 0;
}

LUOGU P5061 秘密任务(背包+二分图染色)的更多相关文章

  1. 洛谷 P5061 秘密任务 —— 二分图

    题目:https://www.luogu.org/problemnew/show/P5061 首先,“配合默契”就是连边的意思: 但发现答案不好统计,因为有连边的两个点可以分在一组,也可以不分在一组: ...

  2. [多校联考2019(Round 5 T2)]蓝精灵的请求(二分图染色+背包)

    [多校联考2019(Round 5)]蓝精灵的请求(二分图染色+背包) 题面 在山的那边海的那边住着 n 个蓝精灵,这 n 个蓝精灵之间有 m 对好友关系,现在蓝精灵们想要玩一个团队竞技游戏,需要分为 ...

  3. LUOGU 1525 关押罪犯 - 并查集拆点(对立点) / 二分+二分图染色

    传送门 分析: 并查集: 第一步先将所有矛盾从大至小排序,显然先将矛盾值大的分成两部分会更优. 普通的并查集都只能快速合并两个元素至同一集合,却不能将两个元素分至不同集合. 对于将很多数分成两个集合, ...

  4. LOJ P1155 双栈排序 二分图染色 图论

    https://www.luogu.org/problem/show?pid=P1155 题解: https://www.byvoid.com/zhs/blog/noip2008-twostack 开 ...

  5. NOIP2008双栈排序[二分图染色|栈|DP]

    题目描述 Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈S1 操作b 如果栈S1 ...

  6. 洛谷P1330封锁阳光大学[二分图染色]

    题目描述 曹是一只爱刷街的老曹,暑假期间,他每天都欢快地在阳光大学的校园里刷街.河蟹看到欢快的曹,感到不爽.河蟹决定封锁阳光大学,不让曹刷街. 阳光大学的校园是一张由N个点构成的无向图,N个点之间由M ...

  7. POJ2942 Knights of the Round Table[点双连通分量|二分图染色|补图]

    Knights of the Round Table Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 12439   Acce ...

  8. 【POJ 2942】Knights of the Round Table(点双连通分量,二分图染色)

    圆桌会议必须满足:奇数个人参与,相邻的不能是敌人(敌人关系是无向边). 求无论如何都不能参加会议的骑士个数.只需求哪些骑士是可以参加的. 我们求原图的补图:只要不是敌人的两个人就连边. 在补图的一个奇 ...

  9. Codeforces Round #311 (Div. 2) D - Vitaly and Cycle(二分图染色应用)

    http://www.cnblogs.com/wenruo/p/4959509.html 给一个图(不一定是连通图,无重边和自环),求练成一个长度为奇数的环最小需要加几条边,和加最少边的方案数. 很容 ...

随机推荐

  1. js动态添加的元素绑定事件

    最近做的项目要实现一个动态添加动态删除的功能,思考了一下,该怎么给动态添加的元素绑定事件.最后觉得有两种方式比较可靠,第一种是在动态添加的html代码里添加oclick事件,然后给传个唯一的参数来判断 ...

  2. 【算法】一致性Hash算法

    一.分布式算法 在做服务器负载均衡时候可供选择的负载均衡的算法有很多,包括: 轮循算法(Round Robin).哈希算法(HASH).最少连接算法(Least Connection).响应速度算法( ...

  3. 74、Salesforce的String的format方法

    String placehodler = 'Hello {0} , {1} is cool!'; List<String> fillers = new String[]{'Jason',' ...

  4. eclipse 集成 STS 插件

    eclipse 集成 STS 插件 想新建一个 Spring Boot 工程,发现没有,如图:(展示的是集成之后的) eclipse 要和 sts 版本对应的,进入http://spring.io/t ...

  5. 编译Android系统源码和内核源码

    [日期:2016-01-11] 来源:Linux社区  作者:jiangwei [字体:大 中 小]     把我之前编译Android系统源码和内核源码的过程记录一下,因为这个过程真的是受益匪浅,看 ...

  6. Dubbo入门到精通学习笔记(十九):MySQL源码编译安装、MySQL主从复制的配置

    文章目录 MySQL 源码编译安装(CentOS-6.6+MySQL-5.6) 一.服务器配置: 二.源码安装 MySQL5.6.26: MySQL主从复制的配置 环境 依赖课程 MySQL 主从复制 ...

  7. 多条件异步搜索+分页(PHP、 AJAX、ThinkPHP)

    项目中遇到的多条件异步查询及数据分页问题,做了数次尝试,最终虽目的达到,略有繁琐,希望能有更好的处理方式 基于 tp框架 1.html页面代码 <div class="h_cityNa ...

  8. T1212:LETTERS

    [题目描述] 给出一个R * S的大写字母矩阵,一开始的位置为左上角,你可以向上下左右四个方向移动,并且不能移向曾经经过的字母.问最多可以经过几个字母.roe× [输入] 第一行,输入字母矩阵行数R和 ...

  9. upc组队赛14 Evolution Game【dp】

    Evolution Game 题目描述 In the fantasy world of ICPC there are magical beasts. As they grow, these beast ...

  10. java中的三大特性

    java的三大特性是封装.继承.多态: 继承是OOD(面向对象设计)为了更好的建模,编程的时候是OOP(面向对象编程)提高代码的复用性.这里有个注意点:一个类只有一个直接的父类,但不是只有一个父类. ...