chordal graph-弦图
1.定义
大家都知道子图的概念,这里加入一个诱导子图(induced subgraph)的定义:
为了更好的理解弦图的概念,我们引进单纯点(simplicialvertex)的定义:N(v)表示与点v相邻的所有点集。一个点称为单纯点当{v}+N(v)的诱导子图为一个团({v}+N(v)的点集以及由这些点集在原图中的所有边的构成的图是一个团)如下图中的红圈圈住的点为单纯点:
团:给定无向图G=(V,E)。如果U包含于V,且对任意u∈U,v∈U,存在边(u,v)∈E,则称U是G的完全子图。G的完全子图U是G的团当且仅当U不包含在G的更大的完全子图中。G的最大团是指G中所含顶点数最多的团。下图G中,子集{1,2}是G的大小为2的完全子图。这个完全子图不是最大团,因为它被G的更大的完全子图{1,2,5}包含。{1,2,5}是G的最大团。{1,4,5}和{2,3,5}也是G的最大团:
2.判断方法
MCS(G, order)
{
for all vertices v in G do
Label[v] = 0
for i from n to 1 do
{
choose an unnumbered vertex v with largest Label
order[v] = i
for all unnumbered vertices u adjacent to v do
Label[u]++
}
}
然后判断该序列是否是完美消除序列:对于每一个vi,找到{vi+1,vi+2,…,vn}中与vi相邻的标号最小的点vj,
判断其它{vi+1,vi+2,…,vn}中与vi相邻的点是否与vj相邻,若不相邻则不是完美消除序列。从而可以判断是不是弦图。
3.扩展
会惊奇地发现它也是弦图。给定一些区间,定义一个相交图为每个顶点表示一个区间,两个点有边当且仅当两个区间的交集非空,如下图所示的区间图:
/*************************************************************************
> File Name: 67.cpp
> Author: wjzdmr
> Mail: wjzdmr@gmail.com
> Created Time: 2014年09月17日 星期三 20时03分40秒
************************************************************************/
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <cctype>
#include <map>
#include <set>
#include <bitset>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <cassert>
#include <limits>
#include <fstream>
using namespace std;
#define mem(A, X) memset(A, X, sizeof A)
#define pb(x) push_back(x)
#define mp(x,y) make_pair((x),(y))
#define vi vector<int>
#define all(x) x.begin(), x.end()
#define foreach(e,x) for(__typeof(x.begin()) e=x.begin();e!=x.end();++e)
#define sz(x) (int)((x).size())
#define sl(a) strlen(a)
#define rep(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i))
#define Rep(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i))
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define dbg(a) cout << a << endl;
#define fi first
#define se second
typedef long long int64;
int gcd(const int64 &a, const int64 &b) { return b == 0 ? a : gcd(b, a % b); }
int64 int64pow(int64 a, int64 b){ if (b == 0) return 1; int64 t = int64pow(a, b / 2); if (b % 2) return t * t * a; return t * t; }
const int inf = 1 << 30;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int MAX_N = 10005;
int n, m;
vi arr[MAX_N];
int R[MAX_N], SA[MAX_N], label[MAX_N];
priority_queue <pair<int, int> > heap;
void work()
{
Rep(i, 1, n) {
arr[i].clear();
}
int u, v;
Rep(i, 1, m) {
scanf("%d%d", &u, &v);
arr[u].pb(v);
arr[v].pb(u);
}
fill(R + 1, R + n + 1, -1);
fill(label + 1, label + n + 1, 0);
Rep(i, 1, n) {
heap.push(mp(0, i));
}
//MCS求弦图的完美消除序列
for (int cnt = n; cnt >= 1; ) {
int id = heap.top().se;
heap.pop();
if (R[id] != -1)
continue;
SA[cnt] = id;
R[id] = cnt--;
rep(i, 0, sz(arr[id])) {
int u = arr[id][i];
if (R[u] != -1)
continue;
label[u]++;
heap.push(mp(label[u], u));
}
}
}
void Color(int u)
{
rep(i, 0, sz(arr[u])) {
int v = arr[u][i];
if (label[v] == -1)
continue;
R[label[v]] = u;
}
for (int i = 1; label[u] == -1; ++i) {
if (R[i] != u)
label[u] = i;
}
}
int Color_Graph()
{
fill(label + 1, label + n + 1, -1);
fill(R + 1, R + n + 1, -1);
for (int i = n; i > 0; --i)
Color(SA[i]);
int ans = 0;
Rep(i, 1, n)
ans = max(ans, label[i]);
return ans;
}
int main()
{
while (cin >> n >> m) {
work();
cout << Color_Graph() << endl;
}
return 0;
}