bzoj1006 [HNOI2008]神奇的国度
1006: [HNOI2008]神奇的国度
Time Limit: 20 Sec Memory Limit: 162 MB
Submit: 2304 Solved: 1043
Description
K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等的存在.所谓N边关系,是指N个人 A1A2...An之间仅存在N对认识关系:(A1A2)(A2A3)...(AnA1),而没有其它认识关系.比如四边关系指ABCD四个人 AB,BC,CD,DA相互认识,而AC,BD不认识.全民比赛时,为了防止做弊,规定任意一对相互认识的人不得在一队,国王相知道,最少可以分多少支队。
Input
第一行两个整数N,M。1<=N<=10000,1<=M<=1000000.表示有N个人,M对认识关系. 接下来M行每行输入一对朋友
Output
输出一个整数,最少可以分多少队
Sample Input
1 2
1 4
2 4
2 3
3 4
Sample Output
HINT
一种方案(1,3)(2)(4)
Source
题目大意:给出一个图,此图中不存在点数>3的环(这里的环指内部没边相连的环),问给此图的点染色,使得相邻的点颜色不同,所需要的最少颜色种类
分析:
首先此题有论文:
弦图与区间图-陈丹琦
http://wenku.baidu.com/link?url=Vz-Cjrq24tvblbk0l1I4IPYYfZ82jkGpzGBoNBDhi6qSCJko9hSTcrKGWrunO91TlU_eei4KBIdw1Y9U9bTnZOUJCPau8qTmUzcIzik_nQ3
简述一下:(省略一大堆证明之类的东东)
首先,像题目中那样的图(不存在点数>3的环)就做弦图,
一些点v1, v2, v3, ....., vn以及这些点之间相连的边叫这些点的诱导子图,
一些点的诱导子图如果是完全图,那就叫做团,
一个图中与一个点 i 相连的点为N( i ),
一个图中,如果有一个点 i 与N( i )的诱导子图是完全图的话,那么这个点 i 叫做单纯点
弦图中有样东西叫完美消除数列,这个数列是这样的:数列中第 i 个点在数列第 i - n 个点的诱导子图中是单纯点
怎么求完美消除序列:
我们定义Label[i]表示第 i 个点与多少已标记的点相连,一开始所有的点都没有标记,
然后选择一个Label最大的点 i ,标记这个点,并更新其他点的label,
按照标记顺序得到的数列便叫完美消除序列
这个可以用堆(优先队列)做,复杂度 nlogn,
也可以优化至O(n+m),建n-1个链表List,分别表示Label为x的有哪些(存入List[x]),
High记录最大的Label,
选择时:每次选择Label最大的点,从list[high]中从前往后选(注意忽略已经在完美消除序列中的点),选择到后,在list中删除此点,并加入完美消除序列
更新时:每次更新Label,比如从x改为x+1,那么不需要删除List[x]中的那个点,在List[x+1]的后面加入即可
复杂度O(n+m)
当然,本程序使用了优先队列
根据这个完美消除序列染色,每次染色都尽量染编号小(就是说尽量染以前的颜色,并保证不与 相邻的 已经染色的 点的颜色相同)的颜色,得到的颜色数就是答案,即最小染色数
综上所述,本题得解:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <ctime>
using namespace std;
typedef long long LL;
#define For(i, s, t) for(int i = (s); i <= (t); i++)
#define Ford(i, s, t) for(int i = (s); i >= (t); i--)
#define MIT (2147483647)
#define INF (1000000001)
#define MLL (1000000000000000001LL)
#define sz(x) ((bnt) (x).size())
#define clr(x, y) memset(x, y, sizeof(x))
#define puf push_front
#define pub push_back
#define pof pop_front
#define pob pop_back
#define ft first
#define sd second
#define mk make_pair
inline void SetIO(string Name) {
string Input = Name+".in",
Output = Name+".out";
freopen(Input.c_str(), "r", stdin),
freopen(Output.c_str(), "w", stdout);
} const int N = , M = ;
typedef pair<int, int> II;
int First[N], To[M*], Next[M*], Tot;
int n, m;
int Label[N], High, Que[N];
priority_queue<II> S;
bool Visit[N];
int Color[N], Draw[N]; inline void Insert(int u, int v) {
Tot++;
To[Tot] = v, Next[Tot] = First[u];
First[u] = Tot;
} inline void Input() {
scanf("%d%d", &n, &m);
For(i, , m) {
int u, v;
scanf("%d%d", &u, &v);
Insert(u, v), Insert(v, u);
}
} inline void Solve() {
High = , clr(Label, ), clr(Visit, );
For(i, , n) S.push(II(, i));
For(t, , n) {
II It = S.top();
while(Visit[It.sd]) {
S.pop();
It = S.top();
}
Visit[It.sd] = , Que[t] = It.sd;
for(int v, Tab = First[It.sd]; Tab; Tab = Next[Tab])
if(!Visit[v = To[Tab]]) {
Label[v]++;
S.push(II(Label[v], v));
}
} int Ans = ;
For(i, , n) Color[i] = n+;
clr(Draw, );
For(t, , n) {
int x = Que[t];
for(int Tab = First[x]; Tab; Tab = Next[Tab])
Draw[Color[To[Tab]]] = t;
Color[x] = ;
while(Draw[Color[x]] == t) Color[x]++;
Ans = max(Ans, Color[x]);
} printf("%d\n", Ans);
} int main() {
SetIO("");
Input();
Solve();
return ;
}
有些题外话也讲讲,都是我看论文懂得:
求弦图的最大独立集:最大独立集即为选择最多的点,使它们两两没边相连
根据完美消除序列选择点,每次如果当前点与以前选的点没边相连就选,不能选略过,
最终得到的点即为最大独立集
最大独立集为最少团覆盖(即用最少的团覆盖所有点):
是哪些团呢?-> 设最大独立集的点为 p1, p2, p3, ... pn, 那这些团为 p1+N(p1), p2+N(p2), .... pn+N(pn),如果与前面的团有重复的点,可以忽略那些点
判定弦图:zju1015
先按照求完美消除序列的方法求出来一个数列,
如果求出来的数列是完美消除序列,那么这个图就是弦图
判定完美消除序列:
我们首先可以暴力判定这个数列 pi, pi+1, pi+2.....pn是否两两相连,构成一个完全图,
复杂度很高
但也可以根据弦图的性质优化一下,
假设在pi,pi+1,....pn中与pi相连的点为 v1, v2, v3.... vn,
那么只需判断v1与 v2,v3,v4...vn是否相连即可
复杂度O(n+m)
还有区间图,区间图都可以转化为弦图,
即相互覆盖的两个线段连条边,
所以求选择最多线段不互相覆盖的问题可以转化为弦图的最大独立集来做来做,
等等等等,陈丹琦实在太厉害了,我是在太垃圾了。。。。。
我真是蒟蒻
bzoj1006 [HNOI2008]神奇的国度的更多相关文章
- [bzoj1006](HNOI2008)神奇的国度(弦图最小染色)【太难不会】
Description K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则. 他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关 ...
- [BZOJ1006] [HNOI2008] 神奇的国度 (弦图)
Description K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系 ...
- BZOJ1006:[HNOI2008]神奇的国度(弦图染色)
Description K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的. 为了巩固三角关系,K国禁止四边关系,五边关 ...
- 【bzoj1006】[HNOI2008]神奇的国度
1006: [HNOI2008]神奇的国度 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 3114 Solved: 1401[Submit][Sta ...
- BZOJ 1006 [HNOI2008] 神奇的国度(简单弦图的染色)
题目大意 K 国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即 AB 相互认识,BC 相互认识,CA 相互认识,是简洁高效的.为了巩固三角关系,K 国禁止四边关系,五边关系等 ...
- 【BZOJ】1006: [HNOI2008]神奇的国度 弦图消除完美序列问题
1006: [HNOI2008]神奇的国度 Description K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则. 他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的 ...
- bzoj 1006: [HNOI2008]神奇的国度 弦图的染色问题&&弦图的完美消除序列
1006: [HNOI2008]神奇的国度 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 1788 Solved: 775[Submit][Stat ...
- BZOJ 1006: [HNOI2008]神奇的国度( MCS )
弦图最小染色...先用MCS求出完美消除序列然后再暴力染色... ------------------------------------------------------------------- ...
- 【BZOJ1006】神奇的国度(弦图)
[BZOJ1006]神奇的国度(弦图) 题面 BZOJ 题解 直接参考弦图的做法 #include<iostream> #include<cstdio> #include< ...
随机推荐
- Web 项目下载图片简单处理方式
1.如果图片头信息有 "Content-Disposition", "attachment; filename="fileName" 那么直接使用 i ...
- Swift - 代码创建单例
创建单例的方法 import UIKit //创建一个单例类 class SingleInstance: NSObject { //在单例类中,有一个用来共享数据的数组 var datas = [St ...
- NYOJ题目111分数加减法
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsEAAAKBCAIAAAA5i+FPAAAgAElEQVR4nO3dPXLbugMv7LsJ916Iay ...
- golang debug with LiteIDE
golang 的调试比较麻烦,debug stop into 无法跳转到自己写的代码,但是能够跳转到系统提供的代码. 以下是简单的测试代码: package main import ( "f ...
- JavaScript - UnderScore
UnderScore 第一步 call(this) (function() {}.call(this)); 一些简单的初始化操作 (function() { var root = this; var ...
- uC/OS II原理分析及源码阅读(一)
uC/OS II(Micro Control Operation System Two)是一个可以基于ROM运行的.可裁减的.抢占式.实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,是和 ...
- 安装wine的问题
- HR外包系统 - 账款
01 账款-服务费,注意多币种以及收款对象和联系人的设置 02 代收代付,注意多币种以及收款对象和联系人的设置 03 账单要保存服务费计算的整个过程,便于后面出报表和数据分析 04 出报表时,要考虑 ...
- 5.linux内核模块基础,内核模块学习
linux内核模块基础 一.定义 Linux 内核的整体结构非常庞大,其包含的组件也非常多,如何使用这些组件呢: 方法 1:把所有的组件都编译进内核文件,即:zImage 或 bzImage,但这样会 ...
- Android入门开发之SD卡读写操作(转)
SD卡的读写是我们在开发android 应用程序过程中最常见的操作.下面介绍SD卡的读写操作方式: 1. 获取SD卡的根目录 String sdCardRoot = Environment.getE ...