UVALIVE 6189

来源:互联网 发布:火车票网上抢票软件 编辑:程序博客网 时间:2024/05/21 09:28

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

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

#include <cstdio>#include <iostream>#include <cstring>#include <queue>#define N 105#define M 20005using 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;}


原创粉丝点击