题意:

给你一个图,问你有多少个方案把他分成连个新的图。使得一个图是一个团,另外一个是独立集

一些闲话:

以前做过一次这个题..当时听说爆搜可以过,就无脑莽过去了..

也没有思考为什么爆搜能过,或者有没有非爆搜的方法..

其实这题是有非爆搜,并且是线性的做法

题解:

先考虑这么一个事实:加入我们得到了一个合法解,那么剩下的合法解肯定可以通过下面的调整得到:

1.从团里面丢一个点到独立集里面

2.从独立集里面丢一个点到团里面

3.独立集和团交换一个点

显然,所有操作都不可能设计独立集/团里面的两个点,这样就使问题好办了许多

考虑怎么得到一个合法解

一般来说,我们可以贪心来做,按度数排一个序,然后从大到小看,能放到团里面就放到团里面,否则丢到独立集里面

最后看一下独立集是否合法..

尝试证明这个贪心的正确性,我们只需要证明只要有解,这样一定可以找出来即可

先假设i,j,按度数排序后i在j前面,如果存在一个方案是把i放到独立集里面,而把j放到团里面,不难得到i和j是等价的,因为j要和所有i连出的边连边

因此这两个点谁放哪里都一样

于是我们就得到了一个合法解

定义可以自由转化阵营的是自由点,否则是非自由点

两个都是自由点的方案很好算,两个都是非自由点的可以发现是没有的

那么各有一般怎么算..其实也是暴力就好了,看看唯一影响这个点非自由的是不是自由点就好了

这个部分可以写成O(m)

至于排序,可以用桶排来解决,因此总复杂度就是O(n+m)

但是因为这个题数据很不好造..因此爆搜什么的很难卡..n,m如果同阶,显然团的个数也会很少,因此,就算暴力一点写成O(n^2+m)也应该可以过n,m同阶的点

然后就没什么了

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
const int N=;
int T;
int n,m;
struct qq
{
int x,y,last;
}e[N*N*];int num,last[N];
void init (int x,int y)
{
e[++num].x=x;e[num].y=y;
e[num].last=last[x];
last[x]=num;
}
int du[N];
int id[N];
bool cmp (int x,int y) {return du[x]>du[y];}
bool in[N];
int o[N];
int read ()
{
char ch=getchar();int x=;
while (ch<''||ch>'') ch=getchar();
while (ch>=''&&ch<='') {x=x*+ch-'';ch=getchar();}
return x;
}
int main()
{
T=read();
while (T--)
{
num=;memset(last,-,sizeof(last));
//scanf("%d%d",&n,&m);
n=read();m=read();
for (int u=;u<=n;u++) du[u]=;
for (int u=;u<=m;u++)
{
int x,y;
//scanf("%d%d",&x,&y);
x=read();y=read();
init(x,y);init(y,x);
du[x]++;du[y]++;
}
for (int u=;u<=n;u++) id[u]=u,in[u]=false;
sort(id+,id++n,cmp);
int cnt=;//有多少个
for (int u=;u<=n;u++)
{
int x=id[u];int sum=;
for (int i=last[x];i!=-;i=e[i].last) sum=sum+in[e[i].y];
if (sum==cnt) {in[x]=true;cnt++;}
}
bool tf=true;
for (int u=;u<=num;u++) if (in[e[u].x]==false&&in[e[u].y]==false) {tf=false;break;}
if (tf==false) {printf("0\n");continue;}
int cnt1=,cnt2=;
for (int u=;u<=n;u++)
{
o[u]=;
for (int i=last[u];i!=-;i=e[i].last) o[u]=o[u]+(in[u]!=in[e[i].y]);
if (in[u]==true&&o[u]==) cnt1++;
if (in[u]==false&&o[u]==cnt) cnt2++;
}
int ans=(cnt!=n);//printf("%d %d\n",ans,n);
ans=ans+(cnt1+)*(cnt2+)-; if (cnt==&&cnt1==) ans--;
// printf("%d %d %d %d\n",ans,cnt1,cnt2,cnt);
int tot=;
for (int u=;u<=n;u++) if (in[u]&&du[u]==cnt-) tot++;
for (int u=;u<=n;u++) if (in[u]==false&&du[u]==cnt-)
{
int now=;
for (int i=last[u];i!=-;i=e[i].last)
{
int y=e[i].y;
if (in[y]&&du[y]==cnt-) now++;
}
// if (now>tot) printf("FUCK!\n");
ans=ans+tot-now;
}
printf("%d\n",ans);
}
return ;
}

bzoj 3579: 破冰派对的更多相关文章

  1. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  2. < < < 2013年国家集训队作业 > > >

    完成题数/总题数:  道/37道 1.  A1504. Book(王迪): 数论+贪心   ★★☆        2013中国国家集训队第二次作业 2.  A1505. 树(张闻涛): 倍增LCA+可 ...

  3. 【清北学堂2018-刷题冲刺】Contest 9

     前几天本蒟蒻一直在颓废所以这篇题解咕了很久,而且最后一个题目不太会,最终也没完成,非常惭愧.  写这些题目收获相当大.后面的日子呢,我会继续着手刷NOIP题目和Codeforces题目.  到这里就 ...

  4. BZOJ 1631==USACO 2007== POJ 3268 Cow Party奶牛派对

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 19226   Accepted: 8775 Description One ...

  5. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  6. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  7. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  8. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  9. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

随机推荐

  1. 【android】获取本机ip地址

    方法是利用网址:http://pv.sohu.com/cityjson?ie=utf-8,返回String类型的ip地址: public static String getNetIp() { Stri ...

  2. 6个步骤,全方位掌握 Kafka

    毋庸置疑,目前 Apache Kafka 是整个消息引擎领域的执牛耳者,也是大数据生态圈中颇为重量级的一员. 从最早诞生于 LinkedIn 的"分布式消息系统",到现在集成了分发 ...

  3. hdu6331 /// Floyd+分块DP

    题目大意: 给定单向图的n m 为点数和单向边数 接下来m行给定 u v w 为边的起点终点和长度 给定q 为询问个数 接下来q行给定 x y k 求从x到y至少经过k条边的最短路长度 https:/ ...

  4. 2018-2-13-win10-uwp-让焦点在点击在页面空白处时回到textbox中

    title author date CreateTime categories win10 uwp 让焦点在点击在页面空白处时回到textbox中 lindexi 2018-2-13 17:23:3 ...

  5. 提升方法(boosting)详解

    提升方法(boosting)详解 提升方法(boosting)是一种常用的统计学习方法,应用广泛且有效.在分类问题中,它通过改变训练样本的权重,学习多个分类器,并将这些分类器进行线性组合,提高分类的性 ...

  6. QueryList.class.php很方便的一个采集数据工具。

    QueryList.class.php是一个非常方面的网站数据采集工具.可以在这个上面采集别的网站数据. /*调用开始*/ require 'QueryList.class.php';header(' ...

  7. python基础教程2第20章 项目1:即时标记

    simple_markup.py import sys, re from util import * print('<html><head><title>...&l ...

  8. IDEA工具下Mybaties框架快速入门程序

    本篇文章介绍在IDEA工具下mybatis快速入门程序分为以下五步 ​ 1 添加依赖包 ​ 2 编写pojo对象 ​ 3 编写映射文件 ​ 4 编写核心配置文件 ​ 5 测试框架 详细如下 建立Mod ...

  9. Dart编程循环

    有时,某些指令需要重复执行.循环是一种理想的方法.循环表示必须重复的一组指令.在循环的上下文中,重复被称为迭代 . 下图说明了循环的分类 让我们开始讨论确定循环.迭代次数是确定/固定的循环称为确定循环 ...

  10. PDO基础

    //PDO:数据访问抽象层 $dsn = "mysql:dbname=mydb;host=localhost";//造PDO对象 $pdo = new PDO($dsn," ...