【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;

}

 

 

你可能感兴趣的:(tr)