POJ 1094 Sorting It All Out (拓扑排序,有向图判环)

来源:互联网 发布:蒙特卡洛模拟算法 编辑:程序博客网 时间:2024/05/29 00:34

题目链接:http://poj.org/problem?id=1094

思路:因为要找第一个满足拓扑排序的或是有环的,所以要从第一个输入就开始判断。这里要注意一点,如果判断时发现有环了,那么后面都不用管了,答案就是有环;如果判断时发现满足拓扑排序了,那么后面也不用管了(不管后面有没有和前面形成环),答案就是满足拓扑。

        先判断环,再判断拓扑排序比较方便。判环时,可以用DFS,方法如下,令vis[i] == 0表示结点i还没被访问、vis[i] == -1表示结点正在访问、vis[i] == 1表示节点已访问完成,如果在访问的过程中发现某个子结点的vis为-1,则存在环。若结点i访问完成并且没有环,则令vis[i] == 1,后面再扫到v时直接跳过即可(因为i点不在环中)。

       判断完环后,再判断拓扑排序就简单了(这里的拓扑排序是必须满足任意两点都可比较)。从图中找入度为0的结点,若个数大于1,则不满足,否则删除该点即该点所连的边,继续重复前面的过程,直到所有点被删光为止。


    

#include<cstdio>#include<cstring>#include<string>#include<cctype>#include<iostream>#include<set>#include<map>#include<cmath>#include<sstream>#include<vector>#include<stack>#include<queue>#include<bitset>#include<algorithm>#define fin() freopen("A.txt","r",stdin)#define fout() freopen("B.txt","w",stdout)typedef long long ll;using namespace std;const int maxn = 30;string ans;vector<int> G[maxn];int vis[maxn];int degree[maxn];int n, m;bool dfs(int u) {  if(vis[u] == -1) return false;  vis[u] = -1;  for(int i = 0; i < G[u].size(); i++) {    int v = G[u][i];    if(vis[v] == 1) continue;    if(!dfs(v)) return false;  }  vis[u] = 1;  return true;}bool is_circle() {  memset(vis, 0, sizeof vis);  for(int i = 0; i < n; i++) if(!vis[i]){    if(!dfs(i)) return true;  }  return false;}bool is_topo() {  string s;  int ru[maxn];  memset(vis, 0, sizeof vis);  for(int i = 0; i < n; i++) ru[i] = degree[i];  bool ok = true;  for(;;) {    int cnt = 0, temp = 0;    for(int i = 0; i < n; i++) {      if(!ru[i] && !vis[i]) {        cnt++; vis[i] = 1; temp = i;      }    }    if(cnt != 1) {      if(cnt > 1) ok = false;      break;    }    s += (char)(temp+'A');    for(int i = 0; i < G[temp].size(); i++) {      int v = G[temp][i];      ru[v]--;    }  }  if(ok) ans = s;  return ok;}int main() {  while(scanf("%d%d", &n, &m) && n) {    memset(degree, 0, sizeof degree);    for(int i = 0; i < n; i++) G[i].clear();    int circle = 0, topo = 0;        for(int i = 1; i <= m; i++) {      char s[5]; scanf("%s" ,s);      if(circle || topo) continue;      int u = s[0] - 'A', v = s[2] - 'A';      degree[v]++;      G[u].push_back(v);            if(is_circle()) circle = i;      if(!circle && !topo && is_topo()) topo = i;    }        if(circle) printf("Inconsistency found after %d relations.\n", circle);    else if(topo) printf("Sorted sequence determined after %d relations: %s.\n", topo, ans.c_str());    else printf("Sorted sequence cannot be determined.\n");      }  return 0;}

0 0
原创粉丝点击