HDU1811 Rank of Tetris (并查集)

这道理重要的想法就是利用并查集缩点,将所有相等的点缩成同一个点

因为如果不缩点,那么如果两个数相等,其他的数与他们中任意一个数有关系,就需要把相等的数的关系也都连上,也就是加边。这样十分复杂

我们又可以发现,如果缩点,因为每个点本身有rp值,所以缩成的点能排序的话,原先也可以。就是基于这个原理证明的缩点的正确性

缩完点后进行拓扑排序,我们发现,如果最后拓扑完的点并不是所有点,说明有环,则conflict,如果可以拓扑,说明是信息不完全,因为会有至少两个点是并列的

如果能全排列,说明ok,代码中一些注意点注释。

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int in[N];
int x[N],y[N];
int p[N];
string s[N];
int n,m;
int h[N],e[N],ne[N],idx;
int sum;
void add(int a,int b){ //前向星
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void init(){
    memset(h,-1,sizeof h);
    idx=0;
    memset(in,0,sizeof in);
}
int find(int x){
    if(p[x]!=x){
        p[x]=find(p[x]);
    }
    return p[x];
}
void topo(){
    int i;
    queue<int> q;
    for(i=0;i<n;i++){
        if(!in[i]&&p[i]==i)//一定要找根节点且入度为0,不然多加了点
        q.push(i);
    }
    if(q.size()==0){
        cout<<"CONFLICT"<<endl;
        return  ;
    }
    int top=0;
    while(q.size()){
        if(q.size()>1){
            top=1; //不能直接break,因为如果冲突加不完全则输出冲突
        }
        int u=q.front();
        q.pop();
        sum--;
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            in[j]--;
            if(!in[j])
            q.push(j);
        }
    }
    if(sum>0)
    cout<<"CONFLICT"<<endl;
    else{
        if(top==1)
        cout<<"UNCERTAIN"<<endl;
        else
        cout<<"OK"<<endl;
    }
}
int main(){
    int i;
    while(cin>>n>>m){
        for(i=0;i<n;i++)
        p[i]=i;
        init();
        sum=n;
        for(i=1;i<=m;i++){
            cin>>x[i]>>s[i]>>y[i];
            if(s[i]=="="){
                int pa=find(x[i]),pb=find(y[i]);
                if(pa!=pb){
                    p[pa]=pb;
                    sum--;//记得缩完点后个数变少
                }
            }
        }
        int sign=0;
        for(i=1;i<=m;i++){
            int pa=find(x[i]),pb=find(y[i]);
            if(pa==pb&&s[i]!="="){//这个地方说明两个相等的点存在相等又存在不等关系,则矛盾,例如a=b,b=c,a>c,这在之前是检查不出来的
                sign=1;
                break;
            }
            if(s[i]==">"){
                add(pa,pb);
                in[pb]++;
            }
            else if(s[i]=="<"){
                add(pb,pa);
                in[pa]++;
            }
        }
        if(sign)
        cout<<"CONFLICT"<<endl;
        else
        topo();
    }
}

原文地址:https://www.cnblogs.com/ctyakwf/p/12358422.html

时间: 2024-10-12 16:54:57

HDU1811 Rank of Tetris (并查集)的相关文章

hdu1811 Rank of Tetris 并查集+拓扑排序

1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #include <queue> 5 using namespace std; 6 struct node//边 7 { 8 int a, b;//顶点 9 char ch;//运算符 10 }c[10005]; 11 vector<int>map[10005];//map数组存贮邻接表 (大佬都是这么开数组的) 12

hdu 1811 Rank of Tetris 并查集+拓扑排序,,提高题

Rank of Tetris Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5672    Accepted Submission(s): 1616 Problem Description 自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球. 为了更好的符合那些爱好者的喜好,Lele又想

hdu 1811 Rank of Tetris (并查集+拓扑排序)

Rank of Tetris Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5415    Accepted Submission(s): 1514 Problem Description 自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球. 为了更好的符合那些爱好者的喜好,Lele又想了

[HDOJ1811]Rank of Tetris(并查集、拓扑排序)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1811 求一堆数据的拓扑序. 处理:x>y就是x到y一条边,x<y就是y到x一条边.关键问题是处理x=y的情况. 假如x=y,就有问题了.假如不处理的话,可能会被当成少处理一个点而使结果编程UNCERTAIN.所以我们考虑用并查集来解决这个问题. 选谁当祖先?题中又给了一个其他的量叫做RP值,这个RP值的规律是序号越大RP值越大.这样我们可以在合并的时候,尽可能地将RP值大的数当成本集合的祖先. 1

hdu 1811Rank of Tetris (并查集 + 拓扑排序)

1 /* 2 题意:这些信息可能有三种情况,分别是"A > B","A = B","A < B",分别表示A的Rating高于B,等于B,小于B. 3 4 现在Lele并不是让你来帮他制作这个高手榜,他只是想知道,根据这些信息是否能够确定出这个高手榜,是的话就输出"OK". 5 否则就请你判断出错的原因,到底是因为信息不完全(输出"UNCERTAIN"),还是因为这些信息中包含冲突(输出&quo

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

Rank of Tetris Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6920    Accepted Submission(s): 1947 Problem Description 自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球. 为了更好的符合那些爱好者的喜好,Lele又想

HDU1811 Rank of Tetris 【缩点】+【拓扑排序】

Rank of Tetris Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5447    Accepted Submission(s): 1526 Problem Description 自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球. 为了更好的符合那些爱好者的喜好,Lele又想

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

Rank of Tetris Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5683    Accepted Submission(s): 1622 Problem Description 自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球. 为了更好的符合那些爱好者的喜好,Lele又想

HDU-1811 Rank of Tetris

拓扑排序难题. 对于相同排名的玩家,我们将他们组成一个集合.这可以用并查集实现. 然后将并查集看成一个点,将所有大于小于的关系转换成集合中的关系,这个过程就可以判断方案是否冲突了. 然后拓扑排序求排名,顺便也就可以判断结果是否唯一了. #include <cstdio> #include <algorithm> #include <iostream> #include <cctype> #include <queue> #include <