BZOJ1006:[HNOI2008]神奇的国度(弦图染色)
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
4 5
1 2
1 4
2 4
2 3
3 4
1 2
1 4
2 4
2 3
3 4
Sample Output
3
HINT
一种方案(1,3)(2)(4)
Solution
弦图染色流程:
初始把所有点的$ID$标为$0$。
每次从没删除的点中取$ID$最大的点$x$,让与$x$相连的点$ID++$,同时删除$x$点。
我用了个$set$维护复杂度也许是$nlogn$的。
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<set> 5 #define N (10009) 6 using namespace std; 7 8 struct Edge{int to,next;}edge[N*200]; 9 int n,m,ans,vis[N],ID[N]; 10 int head[N],num_edge; 11 set<pair<int,int> >s; 12 set<pair<int,int> >::iterator it; 13 14 inline int read() 15 { 16 int x=0,w=1; char c=getchar(); 17 while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();} 18 while (c>='0' && c<='9') x=x*10+c-'0', c=getchar(); 19 return x*w; 20 } 21 22 void add(int u,int v) 23 { 24 edge[++num_edge].to=v; 25 edge[num_edge].next=head[u]; 26 head[u]=num_edge; 27 } 28 29 int main() 30 { 31 n=read(); m=read(); 32 for (int i=1; i<=m; ++i) 33 { 34 int u=read(),v=read(); 35 add(u,v); add(v,u); 36 } 37 for (int i=1; i<=n; ++i) s.insert(make_pair(0,i)); 38 while (!s.empty()) 39 { 40 it=s.end(); it--; s.erase(it); 41 int x=(*it).second; vis[x]=1; 42 for (int i=head[x]; i; i=edge[i].next) 43 if (!vis[edge[i].to]) 44 { 45 s.erase(make_pair(ID[edge[i].to],edge[i].to)); 46 s.insert(make_pair(++ID[edge[i].to],edge[i].to)); 47 } 48 } 49 for (int i=1; i<=n; ++i) ans=max(ans,ID[i]+1); 50 printf("%d\n",ans); 51 }