CSU-ACM2018寒假训练8B-DAG与拓扑排序 F - 字母之序

题目传送门

拓扑排序 加边时动态操作判断


判断三种情况的优先级:

1、是否完成。

2、是否有环。

每次取出入度为0的节点,当总共取出的节点数小于n时,可以判定存在环。

3、是否无法确定。

每次队列中入度为0的节点应当只有一个,若多于一个则其顺序无法确定。


对于优先级,这有一个我认为是坑点的坑点:

当第i步操作已可完成序列时,若i之后的步骤会造成环则不考虑。


POJ上找到了一组数据:

input:
5 5
A<B
B<C
C<D
D<E
E<A

output:
Sorted sequence determined after 4 relations: ABCDE

代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#define  N 100

using namespace std;

int n;
int  s [N];
int cnt[N];
int f[N][N];
bool vis[N];
string ans;
queue <int> que;

bool judge ()
{
	memcpy ( s ,cnt,sizeof(cnt));
	
	bool flag = false , circ = false;
	for (int i=0;i<n;i++)
	{
		if (!s[i])
			que.push(i);
		if (que.size() > 1)
			flag = true;
	}
	
	ans="";
	while (!que.empty())
	{
		int x = que.front();
		que.pop();
		ans += 'A' + x;
		for (int i=1;i<=f[x][0];i++)
		{
			s[f[x][i]]--;
			if (!s[f[x][i]])
				que.push(f[x][i]);
		}
		if (que.size() > 1)
			flag = true;
	}
	
	if (ans.length() != n)
		circ = true;
	
	if (flag)
		ans = "";
	
	return circ;
}

int main ()
{
	int m;
	string a;
	while (~scanf ("%d%d",&n,&m))
	{
		if (!n && !m)
			break;
		
		memset ( f ,0,sizeof( f ));
		memset (cnt,0,sizeof(cnt));
		
		int loc = 0;
		bool circ = false , done = false;
		for (int i=1;i<=m;i++)
		{
			cin>>a;
			f[a[0]-'A'][++f[a[0]-'A'][0]] = a[2]-'A';
			cnt [a[2]-'A'] ++;
			if (!circ)
			{
				if (!done && judge())
				{
					if (!circ)
						printf ("Inconsistency found after %d relations.\n",i);
					circ = true;
				}
				if (ans.length() == n && !loc)
				{
					loc = i;
					done = true;
				}
			}
		}
		
		if (!circ)
			if (!loc)
				printf ("Sorted sequence cannot be determined.\n");
			else
			{
				printf ("Sorted sequence determined after %d relations: ",loc);
				cout<<ans<<"."<<endl;
			}
	}
	return 0;
}

顺便mark一下从小到大排序的优先队列:

priority_queue<int,vector<int>,greater<int> > que;
struct node
{
    friend bool operator< (node n1, node n2)
    {
        return n1.priority < n2.priority;//"<"为从大到小排列,">"为从小打到排列
    }
    int priority;
    int value;
};
priority_queue<node> que;
来源



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值