拓扑排序 加边时动态操作判断
判断三种情况的优先级:
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;
来源