传递闭包的含义指通过传递性推导出尽量多的元素之间的关系,而传递闭包一般都是采用floyd算法。
下面用两道题来实现传递闭包:
Problem 1(POJ3660):
题目链接:http://poj.org/problem?id=3660
题目:
题意:n头牛参加比赛,给你m对关系(譬如给你a和b,那么给的就是a必赢b,当然,b能赢c,那么a也能赢c),问能确定多少头牛的排名。
思路:首先我们用flod算法将所有的关系进行传递,只要u能胜v,那么我们就将d[u][v]设为1,最后如果两者之间有d[u][v]=1或d[v][u]且二者不能同时出现时ans++。
代码实现如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <set> 2 #include <map> 3 #include <queue> 4 #include <stack> 5 #include <cmath> 6 #include <bitset> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 typedef long long ll; 17 typedef pair<ll, ll> pll; 18 typedef pair<int, ll> pil;; 19 typedef pair<int, int> pii; 20 typedef unsigned long long ull; 21 22 #define lson i<<1 23 #define rson i<<1|1 24 #define bug printf("*********\n"); 25 #define FIN freopen("D://code//in.txt", "r", stdin); 26 #define debug(x) cout<<"["<<x<<"]" <<endl; 27 #define IO ios::sync_with_stdio(false),cin.tie(0); 28 29 const double eps = 1e-8; 30 const int mod = 10007; 31 const int maxn = 4500 + 7; 32 const double pi = acos(-1); 33 const int inf = 0x3f3f3f3f; 34 const ll INF = 0x3f3f3f3f3f3f3f; 35 36 int n, m, u, v; 37 int relationship[107][107]; 38 39 int main() { 40 //FIN; 41 scanf("%d%d", &n, &m); 42 memset(relationship, 0, sizeof(relationship)); 43 for(int i = 1; i <= m; i++) { 44 scanf("%d%d", &u, &v); 45 relationship[u][v] = 1; 46 } 47 for(int k = 1; k <= n; k++) { 48 for(int i = 1; i <= n; i++) { 49 for(int j = 1; j <= n; j++) { 50 if(relationship[i][k] && relationship[k][j]) { 51 relationship[i][j] = 1; 52 } 53 } 54 } 55 } 56 int ans = 0, j; 57 for(int i = 1; i <= n; i++) { 58 for(j = 1; j <= n; j++) { 59 if(i == j) continue; 60 if(relationship[i][j] == 0 && relationship[j][i] == 0) { 61 break; 62 } 63 } 64 if(j > n) ans++; 65 } 66 printf("%d\n", ans); 67 return 0; 68 }
Problem 2(POJ1094)
题目链接:http://poj.org/problem?id=1094
题目:
题意:给你n个大写字母,m对大小关系,根据他给的关系推测是否有大小矛盾的情况。如果有矛盾的就输出是在第几组关系时矛盾;如果不矛盾,判断只需要前t对组关系就能推测出他们从小到大的排序;如果没有以上两种情况就输入无法确定。
思路:对于每输入一对关系就跑一次floyd判断一遍,如果能推测出他们的关系,那么就跑一边拓扑排序求出他们从小打到的排序情况;如果有矛盾的关系就直接输出是在第几组关系时矛盾;如果没有以上情况就输出无法确定。
代码实现如下:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <set> 2 #include <map> 3 #include <queue> 4 #include <stack> 5 #include <cmath> 6 #include <bitset> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 typedef long long ll; 17 typedef pair<ll, ll> pll; 18 typedef pair<int, ll> pil;; 19 typedef pair<int, int> pii; 20 typedef unsigned long long ull; 21 22 #define lson i<<1 23 #define rson i<<1|1 24 #define bug printf("*********\n"); 25 #define FIN freopen("D://code//in.txt", "r", stdin); 26 #define debug(x) cout<<"["<<x<<"]" <<endl; 27 #define IO ios::sync_with_stdio(false),cin.tie(0); 28 29 const double eps = 1e-8; 30 const int mod = 10007; 31 const int maxn = 4500 + 7; 32 const double pi = acos(-1); 33 const int inf = 0x3f3f3f3f; 34 const ll INF = 0x3f3f3f3f3f3f3f; 35 36 int n, m, t, flag; 37 char s[1007][5]; 38 int d[30][30], in[30], num[30]; 39 vector<int> G[30]; 40 41 bool floyd() { 42 for(int k = 1; k <= n; k++) { 43 for(int i = 1; i <= n; i++) { 44 for(int j = 1; j <= n; j++) { 45 if(d[i][k] && d[k][j]) { 46 d[i][j] = 1; 47 } 48 } 49 } 50 } 51 for(int i = 1; i <= n; i++) { 52 for(int j = 1; j <= n; j++) { 53 if(i == j) continue; 54 if((d[i][j] && d[j][i]) || (d[i][j] == 0 && d[j][i] == 0)) { 55 return false; 56 } 57 } 58 } 59 return true; 60 } 61 62 void topsort(int m) { 63 t = 0; 64 for(int i = 1; i <= n; i++) { 65 G[i].clear(); 66 } 67 memset(in, 0, sizeof(in)); 68 for(int i = 1; i <= m; i++) { 69 int x = s[i][0] - 'A' + 1, y = s[i][2] - 'A' + 1; 70 G[x].push_back(y); 71 in[y]++; 72 } 73 queue<int> q; 74 for(int i = 1; i <= n; i++) { 75 if(in[i] == 0) { 76 q.push(i); 77 } 78 } 79 while(!q.empty()) { 80 int x = q.front(); q.pop(); 81 num[t++] = x; 82 for(int i = 0; i < G[x].size(); i++) { 83 int v = G[x][i]; 84 in[v]--; 85 if(in[v] == 0) { 86 q.push(v); 87 } 88 } 89 } 90 } 91 92 int main() { 93 //FIN; 94 while(~scanf("%d%d", &n, &m)) { 95 if(n == 0 && m == 0) break; 96 memset(d, 0, sizeof(d)); 97 for(int i = 1; i <= m; i++) { 98 scanf("%s", s[i]); 99 } 100 flag = 0; 101 for(int i = 1; i <= m; i++) { 102 int x = s[i][0] - 'A' + 1, y = s[i][2] - 'A' + 1; 103 d[x][y] = 1; 104 if(floyd()) { 105 printf("Sorted sequence determined after %d relations: ", i); 106 topsort(i); 107 for(int i = 0; i < t; i++) { 108 printf("%c", num[i] - 1 + 'A'); 109 } 110 printf(".\n"); 111 flag = 1; 112 } else { 113 for(int j = 1; j <= n; j++) { 114 for(int k = 1; k <= n; k++) { 115 if(j == k) continue; 116 if((d[j][k] && d[k][j])) { 117 printf("Inconsistency found after %d relations.\n", i); 118 flag = 1; 119 break; 120 } 121 } 122 if(flag) break; 123 } 124 } 125 if(flag) break; 126 } 127 if(!flag) printf("Sorted sequence cannot be determined.\n"); 128 } 129 return 0; 130 }