zoukankan      html  css  js  c++  java
  • HNOI2008]神奇的国度

    题目描述

    K国是一个热衷三角形的国度,连人的交往也只喜欢三角原则.他们认为三角关系:即AB相互认识,BC相互认识,CA相互认识,是简洁高效的.为了巩固三角关系,K国禁止四边关系,五边关系等等的存在.

    所谓N边关系,是指N个人 A1A2...An之间仅存在N对认识关系:(A1A2)(A2A3)...(AnA1),而没有其它认识关系.比如四边关系指ABCD四个人 AB,BC,CD,DA相互认识,而AC,BD不认识.全民比赛时,为了防止做弊,规定任意一对相互认识的人不得在一队,国王相知道,最少可以分多少支队。

    输入输出格式

    输入格式:

    第一行两个整数N,M。1<=N<=10000,1<=M<=1000000.表示有N个人,M对认识关系. 接下来M行每行输入一对朋友

    输出格式:

    输出一个整数,最少可以分多少队

    输入输出样例

    输入样例#1: 复制

    4 5
    1 2
    1 4
    2 4
    2 3
    3 4

    输出样例#1: 复制

    3

    说明

    一种方案(1,3)(2)(4)


    题解

    弦图染色我为什么要学这种没用的东西==

    弦图

    就是一个图中所有长度大于3的环都有至少一条弦

    然后说一下弦图的概念

    单纯点:一个点和与ta相邻的点集所构成的诱导子图是一个团

    所以一个弦图至少有一个单纯点

    完美消除序列:就是一个点的序列\(V_i\)在原图上每一个点\(V_i\),在\(V_{i~n}\)所构成的图中都是一个单纯点

    如果一个图是弦图,那么ta一定有且只有一个完美消除序列

    求完美消除序列?

    就是维护每个点与多少个被染色的点相邻\(d[i]\)

    然后每次都选择\(d[i]\)最大的中放进去最晚的,并对ta进行染色

    再更新与ta相邻的点

    最后把这个选出的点放进序列中并以后不再选ta

    这样就得到了一个倒序的完美消除序列

    然后弦图的极大团就是每个节点最大的势\(d[]+1\)

    弦图的最大独立集

    完美消除序列从前往后能选就选

    弦图的最小团覆盖=最大独立集

    区间图

    就是有一些线段,这些线段相互平行

    然后我们要把边当做点,能相交的线段连边,就构成了区间图

    区间图也是弦图

    然后这玩意儿也可以做区间覆盖的问题但是我不会

    大概就是把区间按照左/右区间排序然后染色或者按照完美消除序列加边就好了

    然后这个题就是求个最大团就没了

    代码

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int M = 10005 ;
    using namespace std ;
    inline int read() {
        char c = getchar() ; int x = 0 , w = 1 ;
        while(c>'9' || c <'0') { if(c=='-') w = -1 ; c = getchar() ; }
        while(c>='0' && c<='9') { x = x*10+c-'0' ; c = getchar() ; }
        return x*w ;
    }
    
    bool vis[M] ;
    vector < int > vec[M] ;
    int n , m , num , hea[M] , best ;
    int cnt , q[M] , d[M] , Ans ;
    struct E { int nxt , to ; } edge[M * 200] ;
    inline void add_edge(int from , int to) {
        edge[++num].nxt = hea[from] ; 
        edge[num].to = to ;
        hea[from] = num ;
    }
    
    
    int main() {
        n = read() ; m = read() ; cnt = n + 1 ;
        for(int i = 1 , u , v ; i <= m ; i ++) {
            u = read() ; v = read() ;
            add_edge(u , v) ; add_edge(v , u) ;
        }
        for(int i = 1 ; i <= n ; i ++) vec[0].push_back(i) ; 
        for(int i = 1 ; i <= n ; i ++) {
            int k = 0 ; bool ftg = true ;
            while(ftg) {
                for(int j = vec[best].size() - 1 ; j >= 0 ; j --) {
                    if(vis[vec[best][j]]) vec[best].pop_back() ;
                    else { k = vec[best][j] ; ftg = false ; break ; }
                }
                if(ftg) -- best ;
            }
            q[--cnt] = k ; vis[k] = true ;
            for(int i = hea[k] ; i ; i = edge[i].nxt) {
                int v = edge[i].to ; if(vis[v]) continue ;
                vec[++d[v]].push_back(v) ; best = max(best , d[v]) ;
            }
        }
        for(int i = n ; i >= 1 ; i --) Ans = max(Ans , d[i] + 1) ;
        cout << Ans << endl ;
        return 0 ;
    }
    
  • 相关阅读:
    shell学习小结
    数据结构基础
    IComparable接口实现自定义类型的排序
    RavenDb进行全文检索实现及数据统计
    移动开发经验总结(monotouch&monodroid)
    Maven pom.xml中的元素modules、parent、properties以及import
    StaticHtml1.0beta
    asp.net 页面静态化
    JQuery常用方法
    ASP.NET无刷新多文件文件上传系统(转载)
  • 原文地址:https://www.cnblogs.com/beretty/p/10297823.html
Copyright © 2011-2022 走看看