BZOJ 1006 [HNOI2008] 神奇的國度(簡單絃圖的染色)

 

題目大意

 

K 國是一個熱衷三角形的國度,連人的交往也只喜歡三角原則。他們認爲三角關係:即 AB 相互認識,BC 相互認識,CA 相互認識,是簡潔高效的。爲了鞏固三角關係,K 國禁止四邊關係,五邊關係等等的存在。所謂 N 邊關係,是指 N 我的 A1 A2 ... An 之間僅存在 N 對認識關係:(A1 A2) (A2 A3) ... (An A1),而沒有其它認識關係,好比四邊關係指 A B C D 四我的 AB,BC,CD,DA 相互認識,而 AC,BD 不認識。全民比賽時,爲了防止作弊,規定任意一對相互認識的人不得在一隊,國王相知道,最少能夠分多少支隊。php

 

Inputhtml

  第一行兩個整數 N,M。1<=N<=10000,1<=M<=1000000。表示有 N 我的,M 對認識關係.。接下來 M 行每行輸入一對朋友ios

Outputide

  輸出一個整數,最少能夠分多少隊優化

 

作法分析

 

根據提題意,不難看出,全部的人構成的關係圖是一個弦圖(長度超過 3 的環中必有一條弦),求出它的完美性消除序列,根據完美消除序列逆序貪心的染色,最終所用的色數就是本題的答案spa

 

完美消除序列的求法:code

 

使用陳丹琦講述的 MCS 法,能夠在 o(n+m) 的時間複雜度中求出一個圖的完美消除序列,並在 o(n+m) 的時間複雜度下判斷這個完美消除序列是否合法,不過,我不知道怎麼在 o(n+m) 的時間複雜度下求出這個完美消除序列,或許是利用桶優化吧,我寫了個堆優化的,時間複雜度也能接受htm

 

求完美消除序列的 MCS 法是倒着解的,也就是先求序列的第 n 個再求序列的第 n-1 個blog

每次選取圖中具備最大標號的點做爲完美消除序列中對應位置的點,並用這個點更新全部和他鄰接的再也不序列中的點的標號值get

 

對於一個弦圖的染色,用完美消除序列能夠很好的解決,按照完美消除序列中的點倒着給圖中的點貪心的然儘量小的顏色

最終,必定可以用最小的顏色數量給圖中的全部點染色

 

本題能夠先求出來這個弦圖的完美消除序列,因爲必定是一個弦圖,因此序列必定合法,直接根據消除序列染色就行

 

更多的和絃圖區間圖相關的知識,請看陳丹琦的PPT:弦圖與區間圖

 

參考代碼

 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <vector>
 5 #include <queue>
 6 
 7 using namespace std;
 8 
 9 const int N=10006;
10 
11 vector <int> arc[N];
12 int n, m, R[N], SA[N], label[N];
13 
14 priority_queue <pair<int, int> > heap;
15 void Construct() {
16     fill(R+1, R+1+n, -1);
17     fill(label+1, label+1+n, 0);
18     for(int i=1; i<=n; i++) heap.push(make_pair(0, i));
19     for(int cnt=n; cnt>=1; ) {
20         int id=heap.top().second;
21         heap.pop();
22         if(R[id]!=-1) continue;
23         SA[cnt]=id, R[id]=cnt--;
24         for(int i=0, len=(int)arc[id].size(); i<len; i++) {
25             int u=arc[id][i];
26             if(R[u]!=-1) continue;
27             label[u]++;
28             heap.push(make_pair(label[u], u));
29         }
30     }
31 }
32 
33 void Color(int u) {
34     for(int i=0, len=(int)arc[u].size(); i<len; i++) {
35         int v=arc[u][i];
36         if(label[v]==-1) continue;
37         R[label[v]]=u;
38     }
39     for(int i=1; label[u]==-1; i++) if(R[i]!=u) label[u]=i;
40 }
41 
42 int Color_Graph() {
43     fill(label+1, label+1+n, -1);
44     fill(R+1, R+1+n, -1);
45     for(int i=n; i>0; i--) Color(SA[i]);
46     int ans=0;
47     for(int i=1; i<=n; i++) ans=max(ans, label[i]);
48     return ans;
49 }
50 
51 int main() {
52     scanf("%d%d", &n, &m);
53     for(int i=1; i<=n; i++) arc[i].clear();
54     for(int i=0, a, b; i<m; i++) {
55         scanf("%d%d", &a, &b);
56         arc[a].push_back(b);
57         arc[b].push_back(a);
58     }
59     Construct();
60     printf("%d\n", Color_Graph());
61     return 0;
62 }
BZOJ 1006

 

題目連接 & AC 通道

 

BZOJ 1006 [HNOI2008] 神奇的國度

相關文章
相關標籤/搜索