拓扑排序之于DAG,就像完美消除序列之于弦图。
就像DAG上的问题许多时候是按照拓扑顺序完成的,弦图上问题按照完美消除序列完成。
#include <iostream>
#include <list>
#include <cstring>
using namespace std;
const int maxKnoten = 11000;
const int maxKanten = 2200000;
int grundzahl[maxKnoten];
bool used[maxKnoten];
list<int> tank[maxKnoten];
int besten;
int ans[maxKnoten];
int farbe[maxKnoten];
bool farbeUsed[maxKnoten];
struct kante
{
int to;
int next;
};
kante e[maxKanten];
int kopf[maxKnoten];
int zahlung[maxKnoten];
int id;
void addEdge(int von,int zu)
{
e[id].to = zu;
e[id].next = kopf[von];
kopf[von] = id;
zahlung[von]++;
id++;
}
void init()
{
id = 0;
memset(kopf,-1,sizeof kopf);
memset(farbe,-1,sizeof farbe);
}
void erneuern(int knot)
{
grundzahl[knot]++;
tank[grundzahl[knot]].push_back(knot);
if (grundzahl[knot] > besten) besten = grundzahl[knot];
}
int erhalten()
{
while (true)
{
while (!tank[besten].empty())
{
int id =tank[besten].front();
if (!used[id])
{
used[id] = true;
return id;
}
tank[besten].pop_front();
}
besten--;
}
return 0;
}
int main(int argc,char * argv[])
{
int kanten,knoten;
cin >> knoten >> kanten;
init();
for (int i = 1;i <= kanten;++i)
{
int a,b;
cin >> a >> b;
addEdge(a, b);
addEdge(b, a);
}
for (int i = 1;i <= knoten;++i)
{
grundzahl[i] = 0;
tank[0].push_back(i);
}
for (int i = 1;i <= knoten;++i)
{
int gute = erhalten();
ans[i] = gute;
int cur = kopf[gute];
while (cur != -1)
{
erneuern(e[cur].to);
cur = e[cur].next;
}
}
farbe[ans[1]] = 0;
for (int i = 2;i <= knoten;++i)
{
memset(farbeUsed,false,(zahlung[ans[i]]+1)*sizeof(bool));
int cur = kopf[ans[i]];
while (cur != -1)
{
if (farbe[e[cur].to] != -1) farbeUsed[farbe[e[cur].to]] = true;
cur = e[cur].next;
}
for (int j = 0;j <= zahlung[ans[i]]+1;++j)
{
if (!farbeUsed[j])
{
farbe[ans[i]] = j;
break;
}
}
}
memset(farbeUsed,false,sizeof(farbeUsed));
for (int i = 1;i <= knoten;++i)
{
farbeUsed[farbe[i]] = true;
}
int zahl = 0;
for (int i = 0;i <= knoten;++i) if (farbeUsed[i]) zahl++;
cout << zahl << endl;
return 0;
}