排序

题面:

        原题链接

题意:

        给定 n 个变量和 m 个不等式(不等式满足传递性),从前往后确定每对变量的关系,看是否有出现矛盾的情况。

题解:

        传递性:设 ⊙ 是定义在集合 S 上的二元关系,若对于 \foralla,b,c\inS,只要有a⊙b且b⊙c,那么必然有a⊙c,那么 ⊙ 具有传递性。而题目里给定的二元关系就是 > ,同时还得确定每对变量的关系,所以问题转换为求传递闭包。

        对于传递闭包的题目,大部分的做法都是 floyd。代码中的 dis[i][j] 表示是否存在 i>j 这一组关系,全都初始化为正无穷。每当添加一对关系,就更新一下 dis 值,在没有出现矛盾的情况下,我们也没有必要跑完整的 floyd,只需要用这条边的两个端点分别作为中转点来更新其他点就行了,因为其他边(其他组关系)没变,用其他点作为中转点不会有任何更新。而对于像 dis[i][j]=dis[j][i]=1 或者 dis[i][i]=1 这种情况就属于矛盾。

代码:

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define eps 1e-10
#define lowbit(x) x&-x
#define int long long
#define INF 1e18
#define PII pair<int,int>
#define fi first
#define se second
#define il inline
il int read() 
{ 
	int x=0,f=0; 
	char ch=0;
	while(!isdigit(ch)) 
	{ 
		f|=(ch=='-');
		ch=getchar();
	}
	while(isdigit(ch)) 
	{ 
		x=(x<<3)+(x<<1)+(ch^48); 
		ch=getchar();
	}
	return f?-x:x;
}
il void write(int x) 
{
	char num[30]; 
	int cnt=0; 
	if(x==0) { putchar('0'); return; }
	if(x<0)
	{
		putchar('-'); 
		x=-x;
	}
	while(x>0) 
	{ 
		num[cnt++]=x%10+'0'; 
		x/=10;
	}
	while(cnt>0) putchar(num[--cnt]);
}
int n,m,dis[205][205];
PII ans[205];
il void floyd(int k)
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
} 
bool check()
{
	for(int i=1;i<=n;i++)
	{
		int cnt=1;//自身本就确定 
		for(int j=1;j<=n;j++)
			if(dis[i][j]!=INF)
				cnt++;
		ans[i]={cnt,i};//比他小的数量 
		for(int j=1;j<=n;j++) 
			if(i!=j&&dis[j][i]!=INF)//比他大的 
				cnt++;
		if(cnt!=n) return 0;
	}
	sort(ans+1,ans+n+1);
	return 1;
}
signed main()
{
	while(cin>>n>>m&&n&&m)
	{
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
				dis[i][j]=INF;//dis[i][j]表示是否存在i>j这一组关系 
		int f=0;
		for(int i=1;i<=m;i++)
		{
			char a,op,b;
			cin>>a>>op>>b;//a<b
			int x=a-'A'+1,y=b-'A'+1;
			if((dis[x][y]!=INF&&!f)||(x==y)) 
			{
				//如果a>b或者a=b都不行 
				printf("Inconsistency found after %d relations.\n",i);
                f=1;
			}
			dis[y][x]=1;//标记关系 
			floyd(x),floyd(y);//以新添加的关系为中点跑floyed,更新图 
			if(!f&&check())
			{
				//如果关系都确定了 
				printf("Sorted sequence determined after %d relations: ",i);
				for(int i=1;i<=n;i++) cout<<char(ans[i].se+'A'-1);
                printf(".\n");
                f=1;	
			} 
		}
		if(!f) printf("Sorted sequence cannot be determined.\n"); 
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值