hdu1811Rank of Tetris(并查集+拓扑排序)

题意很好了解吧,想了很久,总是写一半又把自己否定,写了三个小时才A,药丸。正确思路:现将a==b的合并到并查集,这样就相当于只有<,>这两种情况。
没用队列做,前两次tle,其实主要是忘了break了,造成不必要的循环。用队列大概100ms以内,我750ms左右。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <string.h>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
int pre[10010],cnt[10010],n,m,fn[20011],sn[20011];
bool is_exist[10010];
vector <int > arr[10010];
int fnd(int node)
{return pre[node]==node?node:(pre[node]=fnd(pre[node]));}
void join(int x,int y)
{pre[fnd(x)]=fnd(y);}
void judge(int tn)
{
    bool mflg=false;
    for(int ti=0;ti<tn;ti++)
    {
        int mcnt=0,tl=-1;
        for(int i=0;i<n;i++)
            if(!cnt[fnd(i)]&&tl!=fnd(i)) mcnt++,tl=fnd(i);
        if(mcnt>1) mflg=true;
        bool flg=false;
        for(int i=0;i<n;i++)
            {
                int tmp=fnd(i);
                if(!cnt[tmp])
                {
                    cnt[tmp]--;
                    int sz=arr[tmp].size();
                    for(int j=0;j<sz;j++)
                        cnt[arr[tmp][j]]--;
                    flg=true;
                    break;
                }
            }
        if(!flg) {puts("CONFLICT");return;}
    }
    if(mflg) puts("UNCERTAIN");
    else puts("OK");
}
int main(int argc, char const *argv[])
{   
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        getchar();
        ms(is_exist);
        msc(cnt);
        for(int i=0;i<n;i++) pre[i]=i,arr[i].clear();
        int t=0;
        while(m--)
        {
            int a,b;
            char cmp;
            scanf("%d %c %d",&a,&cmp,&b);
            //is_exist[a]=true,is_exist[b]=true;
            if('>'==cmp) {
                fn[t]=b;
                sn[t++]=a;
            }
            else if('<'==cmp){
                fn[t]=a;
                sn[t++]=b;
            }
            else {
                join(a,b);
            }
        }
        for(int i=0;i<n;i++) cnt[fnd(i)]=0,is_exist[fnd(i)]=true;
        int tnn=0;
        for(int i=0;i<n;i++) if(is_exist[i]) tnn++;
        for(int ti=0;ti<t;ti++)
        {
            int a=fnd(fn[ti]),b=fnd(sn[ti]);
            int sz=arr[a].size();
            bool flg=false;
            for(int j=0;j<sz;j++) if(b==arr[a][j])
     {flg=true;break;}//没有break也没错但会超时
            if(!flg) {arr[a].push_back(b);
            cnt[b]++;}
        }
        //printf("%d\n",tnn );
        //for(int i=0;i<4;i++) printf("%dd \t",cnt[i] );
        judge(tnn);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值