UVALIVE 6189

这道题我做了好几天。。。太弱了。。。最后看别人的代码过的。

首先二分答案,判断可行性时,先可以通过集合间的子集关系的传递性,建立关系矩阵。接着建立一个矩阵存储集合之间的交集是否一定为空,这里有一个性质,如果A是B的子集,且A与B的交集为空,则A为空集。(另外如果A与A交集为空,则A为空集)最后扫描一下不等和交集非空的条件进行判断即可。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#define N 105
#define M 20005
using namespace std;

struct Que{
    int s, l, r;
} Q[M];

bool vis[N];
int n;
int b[N][N], ru[N], f[N][N];
void dfs(int u){
    int i, k;
    vis[u] = 1;
    for(i=1;i<=n;i++)
    if(b[u][i]){
        if(!vis[i]) dfs(i);
        for(k=1;k<=n;k++)
        if(f[i][k])
        f[u][k] = f[k][u] = 1;
    }
}

bool check(int u){
    int i, j, iter, v, k;
    memset(f,0,sizeof(f));
    memset(b,0,sizeof(b));
    for(i=1;i<=n;i++)b[i][i] = 1;
    for(i=1;i<=u;i++){
        int l = Q[i].l, r = Q[i].r;
        if(Q[i].s==1)
            b[l][r] = 1;
        if(Q[i].s==2)
            b[l][r] = b[r][l] = 1;
        if(Q[i].s==4)
            f[Q[i].l][Q[i].r] = f[Q[i].r][Q[i].l] = 1;
    }

    for(k=1;k<=n;k++)
    for(i=1;i<=n;i++)
    for(j=1;j<=n;j++)
    b[i][j] |= b[i][k]&&b[k][j];

    memset(vis,0,sizeof(vis));
    for(i=1;i<=n;i++)
    if(!vis[i]) dfs(i);

    for(i=1;i<=u;i++){
        int l = Q[i].l, r = Q[i].r;
        if(Q[i].s==3){
            if(f[l][l] && f[r][r] ||  b[l][r]&&b[r][l])
                return false;
        }
        if(Q[i].s==5){
            if(f[l][r] || f[l][l] || f[r][r])
                return false;
        }
    }
    return true;
}

int main(){
    int m, i;
    while(scanf("%d%d",&n,&m)&&(n+m)){
        for(i=1;i<=m;i++)scanf("%d%d%d",&Q[i].s,&Q[i].l,&Q[i].r);
        int l = 0, r = m;
        while(l<=r){
            int mid = (l+r)>>1;
            if(check(mid)) l = mid+1;else
            r = mid - 1;
        }
        printf("%d\n",r);
    }
    return 0;
}


你可能感兴趣的:(UVALIVE 6189)