【HNOI】trust 弦图最大独立集

  【题目描述】有n个人,每个人之间都有是否信任的关系,要求找出k个人,使得k个人之间彼此信任,且k最大,保证不信任的关系由多个三元环组成,且三元环之间只可能有公共点,没有公共边,且不存在任意一个节点不属于任意一个三元环。

  【数据范围】

    n<=2000。

  首先我们可以建立信任关系的反图,这样的出的图为弦图,那么我们只需要求出各个块的完美消除序列,然后再通过完美消除序列求出该图的最大独立集就可以了。

  反思:开始脑残求的是最小染色,然后算的相同颜色的数量取max。

 

//By BLADEVIL
#include <cstdio>
#include <cstring>
#define maxn 2010

using namespace std;

int n,l;
int other[maxn*maxn],pre[maxn*maxn],last[maxn],flag[maxn],size[maxn],ans[maxn],que[maxn];

void connect(int x,int y) {
    pre[++l]=last[x];
    last[x]=l;
    other[l]=y;
}

int main() {
    freopen("trust.in","r",stdin); freopen("trust.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++) {
            int x; scanf("%d",&x);
            if (!x) connect(i,j);
        }
    for (int i=n;i;i--) {
        int cur=0;
        for (int j=1;j<=n;j++) if ((size[j]>=size[cur])&&(!flag[j])) cur=j;
        que[i]=cur; flag[cur]=1;
        for (int p=last[cur];p;p=pre[p]) size[other[p]]++;
    }
    //for (int i=1;i<=n;i++) printf("%d ",que[i]); printf("\n");
    memset(flag,0,sizeof flag);
    for (int i=1;i<=n;i++) {
        int cur=que[i];
        if (flag[cur]) continue;
        ans[++ans[0]]=cur;
        for (int p=last[cur];p;p=pre[p]) flag[other[p]]=1;
    }
    printf("%d\n",ans[0]);
    for (int i=1;i<=ans[0];i++) printf("%d ",ans[i]); printf("\n");
    fclose(stdin); fclose(stdout);
    return 0;
}

 

 

posted on 2014-04-01 16:58  BLADEVIL  阅读(415)  评论(0编辑  收藏  举报