hdu1811Rank of Tetris

本文介绍了一道使用并查集进行点压缩,并结合拓扑排序解决冲突检测的算法题目。通过具体代码实现展示了如何处理输入数据,利用并查集简化图结构,再运用拓扑排序判断是否有冲突或不确定的情况。

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1811

题意:中文题。

分析:先用并查集缩下点,然后用拓扑排序判断一些各种情况即可。

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=10010;
const int mod=100000000;
const int MOD1=1000000007;
const int MOD2=1000000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000007;
const int INF=1000000010;
const ll MAX=1ll<<55;
const double pi=acos(-1.0);
typedef double db;
typedef unsigned long long ull;
char s[5];
int nn,f[N],x[N],y[N],z[N];
int tot,d[N],u[N],v[N],pre[N];
void add(int a,int b) {
    v[tot]=b;pre[tot]=u[a];u[a]=tot++;
}
int find_f(int a) {
    return f[a]==a ? a:f[a]=find_f(f[a]);
}
void unio(int a,int b) {
    int fa=find_f(a),fb=find_f(b);
    if (fa!=fb) f[fb]=fa,nn--;
}
int main()
{
    int a,b,i,k,n,m,l,r;
    while (scanf("%d%d", &n, &m)!=EOF) {
        for (i=0;i<n;i++) f[i]=i;
        for (k=0,nn=n,i=1;i<=m;i++) {
            scanf("%d%s%d", &a, s, &b);
            if (s[0]=='<') { k++;x[k]=a;y[k]=b;z[k]=1; }
            else if (s[0]=='>') { k++;x[k]=a;y[k]=b;z[k]=2; }
                else unio(a,b);
        }
        memset(d,0,sizeof(d));
        tot=0;memset(u,-1,sizeof(u));
        for (i=0;i<n;i++) f[i]=find_f(i);
        for (i=1;i<=k;i++)
        if (z[i]==1) add(f[y[i]],f[x[i]]),d[f[x[i]]]++;
        else add(f[x[i]],f[y[i]]),d[f[y[i]]]++;
        k=0;l=1;r=0;
        for (i=0;i<n;i++)
        if (f[i]==i&&d[i]==0) y[++r]=i,x[r]=1;
        for (;l<=r;l++)
            for (i=u[y[l]];i!=-1;i=pre[i]) {
                d[f[v[i]]]--;
                if (d[f[v[i]]]==0) y[++r]=f[v[i]],x[r]=x[l]+1;
            }
        if (r<nn) printf("CONFLICT\n");
        else {
            for (k=1,i=1;i<r;i++)
            if (x[i]==x[i+1]) { k=0;break ; }
            if (!k) printf("UNCERTAIN\n");
            else printf("OK\n");
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值