UVALive_6606_Meeting Room Arrangement(最大独立集)

题型:图论


题意:若干个区间,求最多的区间数,并且这些区间都互不相交。


分析:

相交的区间建边,然后取反图求最大独立集。


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int M=32;
class Maxclique { 
    int n,big,res[M],c[M],v[M],rr[M];
    bool bb,mat[M][M];
public:
    void init(int x) {
        n=x;
        big=0;
        mt(mat,0);
    }
    int getvalue() {
        return big;
    }
    void getsolution() {
        for(int i=0; i<big; i++) {
            printf("%d ",res[i]);
        }
    }
    void add(int x,int y) {
        mat[x][y]=true;
        mat[y][x]=true;
    }
    void inv() { 
        for(int i=0; i<=n; i++) {
            for(int j=0; j<=n; j++) {
                mat[i][j]=!mat[i][j];
            }
        }
    }
    void clique(int num,int u[],int len) {
        int i,j,vn,v[M];
        if(num) {
            if(len+c[u[0]]<=big) return ;
            for(i=0; i<num+len-big&&i<num; i++) {
                for(j=i+1,vn=0; j<num; j++) if (mat[u[i]][u[j]]) v[vn++]=u[j];
                rr[len]=u[i];
                clique(vn,v,len+1);
                if(bb) return;
            }
        } else if (len>big) {
            big=len;
            for (i=0; i<len; i++) res[i]=rr[i];
            bb=true;
        }
    }
    void maxclique() {
        int i,j,vn;
        for(c[i=n-1]=0; i>=0; i--) {
            for(vn=0,j=i+1; j<n; j++) if (mat[i][j]) v[vn++]=j;
            bb=false;
            rr[0]=i;
            clique(vn,v,1);
            c[i]=big;
        }
    }
} gx;
struct IN{
    int s,f;
}g[32];
bool inside(int i,int j){
    int ax=g[i].s;
    int ay=g[i].f;
    int bx=g[j].s;
    int by=g[j].f;
    if(ax>bx){
        swap(ax,bx);
        swap(ay,by);
    }
    if(bx<ay) return true;
    return false;
}
int main(){
    int t,n,a,b;
    while(~scanf("%d",&t)){
        while(t--){
            n=0;
            while(scanf("%d%d",&a,&b),a|b){
                g[n].s=a;
                g[n].f=b;
                n++;
            }
            gx.init(n);
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    if(inside(i,j)){
                        gx.add(i,j);
                    }
                }
            }
            gx.inv();
            gx.maxclique();
            printf("%d\n",gx.getvalue());
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值