[HNOI2008 Kingdom]

[关键字]:图论 弦图的色数

[题目大意]:就是最少的颜色染完所有点使得每条边相邻点都颜色不同,也就是图的色数。

//==========================================================================

[分析]:首先它给出的图是一个弦图,所以有特殊的算法来求色数。首先用最大势算法求出完美消除序列,然后按照序列的逆序进行染色,每次都染这个点没有连着的边中的最小的颜色。最大势算法,每次都找有最多的相连的以被加入的节点的节点。

[代码]:

View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

const int MAXN=10100;

int n,m,ans;
int c[MAXN],b[MAXN],cnt[MAXN];
bool v[MAXN];
vector<int> e[MAXN],O;
vector<int>::iterator it;

int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
{
int x,y;
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
memset(v,0,sizeof(v));
memset(cnt,0,sizeof(cnt));
for (int i=1;i<=n;++i)
{
int Max=-1,Maxj;
for (int j=1;j<=n;++j)
if (!v[j] && cnt[j]>Max) Max=cnt[j],Maxj=j;
v[Maxj]=1;
O.push_back(Maxj);
for (it=e[Maxj].begin();it<e[Maxj].end();++it) ++cnt[*it];
}
//for (int i=0;i<n;++i) printf("%d ",O[i]);
//printf("\n");
c[O[0]]=1;
for (int i=1;i<n;++i)
{
int t=O[i];
for (it=e[t].begin();it<e[t].end();++it)
{
b[c[*it]]=i;
//printf("%d %d %d\n",t,*it,c[*it]);
}
for (int j=1;j<=n;++j)
if (b[j]!=i) {c[t]=j;break;}
}
int ans=0;
for (int i=1;i<=n;++i)
{
if (ans<c[i]) ans=c[i];
//printf("%d ",c[i]);
}
//printf("\n");
printf("%d\n",ans);
return 0;
}



你可能感兴趣的:(2008)