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 }