BZOJ1006

拓扑排序之于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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值