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

转自: https://blog.csdn.net/su20145104009/article/details/47337581

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

题目思路:

1:先建图,然后寻找入度为0的顶点

2:然后找到与这个顶点有关的边和点,删去边,点的入度-1

3.继续寻找下一个入度为0的顶点。。重复2.

对于这道题 用到的知识点 并查集,拓扑排序

并查集是为了处理=的情况,使两个元素合并集合

拓扑排序处理信息不完整和冲突

1.如果出现两个同时入度为0的

2.至于信息冲突的情况就是出现了环,这时候会发现查询入度为0的循环执行不下去了,也就是sum>0.

题目反思:我开始自己写的时候是边建图边处理相等的点,有点复杂,中间有很多小细节都忽视了。而下面的代码是先储存好输出并处理相等的点,再建图,中间的细节就不用考虑了,思路很清晰,值得学习。

代码:

#include <stdio.h>  
#include <string.h>  
#include <vector>  
#include <queue>  
using namespace std;  
struct node//边  
{  
    int a,b;//顶点  
    char ch;//运算符  
}c[10005];  
vector<int>map[10005];//map数组存贮邻接表  
int n,m,sum,in[10005],fa[10005];//in数组表示入度,fa[i]表示顶点i所在集合的根节点  
int find(int x)//查找根节点  
{  
    if(fa[x]!=x) fa[x]=find(fa[x]);  
    return fa[x];  
}  
bool comb(int x,int y)//合并集合  
{  
    x=find(x);  
    y=find(y);  
    if(x==y)  
    return false;  
    else  
    {  
        fa[y]=x;  
        return true;  
    }  
}  
void init()//初始化  
{  
    for(int i=0;i<n;i++)  
    fa[i]=i;  
}  
void top_sort()//queue实现拓扑排序  
{  
    queue<int>s;  
    int flag=0;  
    for(int i=0;i<n;i++)  
    {  
        if(in[i]==0&&fa[i]==i)  
        s.push(i);  
    }  
    while(!s.empty())  
    {  
        if(s.size()>1)//即使发现信息不完整也要继续运行下去,因为如果信息同时不完整和冲突都是CONFLICT  
        flag=1;  
        int pos=s.front();  
        s.pop(),sum--;  
        for(int i=0;i<map[pos].size();i++)  
        {  
            in[map[pos][i]]--;  
            if(in[map[pos][i]]==0)  
            s.push(map[pos][i]);  
        }  
    }  
    if(sum>0) printf("CONFLICT\n");  
    else if(flag) printf("UNCERTAIN\n");  
    else printf("OK\n");  
}  
int main()  
{  
    while(scanf("%d %d",&n,&m)!=EOF)  
    {  
        sum=n;  
        init();  
        memset(map,0,sizeof(map));  
        memset(in,0,sizeof(in));  
        for(int i=0;i<m;i++)  
        {  
            scanf("%d %c %d",&c[i].a,&c[i].ch,&c[i].b);  
            if(c[i].ch=='=')  
            {  
                if(comb(c[i].a,c[i].b))  
                sum--;  
            }  
        }  
        for(int i=0;i<m;i++)  
        {  
            if(c[i].ch=='=')  
            continue;  
            int x=find(c[i].a);  
            int y=find(c[i].b);  
            if(c[i].ch=='>')  
            {  
                map[x].push_back(y);  
                in[y]++;  
            }  
            else  
            {  
                map[y].push_back(x);  
                in[x]++;  
            }  
        }  
        top_sort();  
    }  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值