ZOJ-1060-Sorting It All Out

本文介绍了一种使用拓扑排序解决典型问题的方法,通过构建二进制图并利用图论原理来确定字母间的排序关系。文章详细展示了如何实现拓扑排序算法,并针对特定条件进行判断,以确保排序的有效性和一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这道题AC率大概是30%左右,很典型的拓扑排序。

建立二进制图map[27][27] ,第x行第y列为1代表“第x个字母<第y个字母”

找不到入度为0的字母时(入度为0:该字母只在<号左边出现,未在右边出现),该拓扑排序无解,得出矛盾。但是要注意排除map元素全部为0的情况。

一旦找到当前唯一的入度为0的字母,便记录输出在数组out[]里,去掉输出该字母的顶点和邻边,继续考察剩余图,如此重复,直到输出字母数等于n。

AC以后看了一下这道题的status,我有幸排到第一页尾,于是变本加厉改了好几个int为char,但怎么叫时间也大于00了,只能见好就收,也算是出了口前几天被1059郁闷的恶气,1059我明明对N多测试数据输出正确,但是依然WA让人简直莫明其妙,anyway,1059,1060这两道题都是跟图论有关的。

C++ 00:00.00 396K

//C++ 00:00.00 396K 
#include<stdio.h>
#include
<string.h>

char out[27];
bool map[27][27];
int n,m;
// n indicated the number of objects to sort
// m indicates the number of relations
int sum[27];
bool el[27],hel[27];

void getsum(bool el[])
{
    
int i,j;
    
for(i=0;i<=n;i++)
    {
        sum[i] 
= 0;
    }
    
for(i=1;i<=n;i++)
    {    
        
if(el[i])
        {
            
for(j=1;j<=n;j++)
            {
                
if(map[i][j] && el[j])
                    sum[j]
++;
            }
        }
    }
}

int check()//返回1,成功,返回0,不成,返回-1,矛盾
{
    
int i,countdel=0,pos,count,tot=n;
    
int flag = 1;
    
for(i=0;i<=n;i++)
    {
        el[i] 
= 1;
        hel[i] 
= 1;
        
out[i] = 0;
    }        
    
while(countdel<n)    
    {        
        count
=0;
        getsum(el);
        
for(i=1;i<=n;i++)
        {    
            
if(0==sum[i] && el[i])
            {
                count
++;
                hel[i] 
= 0;
                pos 
= i;
            }    
        }        
        
if(1==count)
        {
            countdel
++;
            el[pos] 
= 0;
            tot
--;
            
out[countdel] = pos + 64;
        }
        
else if(0==count)
        {
            flag 
= -1;
            
return flag;
        }
        
else if(count>1)
        {
            
if(count==tot)
            {
                flag 
= 0;
                
return flag;
            }
            getsum(hel);
            
int key=0;
            
for(i=1;i<=n;i++)
            {    
                
if(0==sum[i] && hel[i])
                {
                    key
++;
                }    
            }    
            
if(0==key)
            {
                flag 
= -1;
                
return flag;
            }
            
else
            {
                flag 
= 0;
                
return flag;
            }
        }
    }    
    
return flag;
}

void solve()
{
    
int i,j,temp;
    
char re[3];
    
for(i=1;i<=m;i++)
    {
        scanf(
"%s", re);
        map[re[
0]-64][re[2]-64= 1;
        temp 
= check();
        
if(1==temp)
        {
            printf(
"Sorted sequence determined after %d relations: ", i);
            
for(j=1;j<=n;j++)
                printf(
"%c"out[j]);
            printf(
"./n");
            
            
for(j=i+1;j<=m;j++)
                scanf(
"%s", re);        
            
return;
        }
        
else if(-1==temp)
        {
            printf(
"Inconsistency found after %d relations./n", i);
            
            
for(j=i+1;j<=m;j++)
                scanf(
"%s", re);    
            
return;
        }        
    }    
    printf(
"Sorted sequence cannot be determined./n", i);
}

int main()
{
//    freopen("01060.txt","r",stdin);
    while(scanf("%d %d"&n, &m)!=EOF && n>0 && m>0)
    {        
        memset(map,
false,sizeof(map));
        solve();
    }
//    fclose(stdin);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值