题目地址:点击打开链接
思路:
拓扑排序的两个性质:
用并查集把成绩相等的人放在一起。
然后根据关系,把他们连起来。
然后拓扑排序。
如果拓扑排序结束之后,拓扑到的边数和输入的边数不同,那么肯定出现环了,那么就是信息错误。0
否则,如果某个时刻出现两个点的入度都为0,那么就出现信息不完整。
其他的就是结果正确了。
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> using namespace std; const int maxn = 10010; struct H { int left,right; char op; }xp[20010]; struct node { int v,next; }lol[20010]; int pre[maxn],head[maxn],in[maxn],edgenum; int find(int x) { return x == pre[x] ? x : pre[x] = find(pre[x]); } void merge(int x,int y) { int a,b; a = find(x); b = find(y); if(a != b) { //pre[x] = y;这都写错。。。 pre[a] = b; } } void add(int x,int y) { lol[edgenum].v = y; lol[edgenum].next = head[x]; head[x] = edgenum++; } int main() { int n,m,i; while(scanf("%d%d",&n,&m) != EOF) { edgenum = 0; for(i=0; i<n; i++) { pre[i] = i; head[i] = -1; in[i] = 0; } int sum = n; for(i=0; i<m; i++) { scanf("%d %c %d",&xp[i].left,&xp[i].op,&xp[i].right); if(xp[i].op == '=') { merge(xp[i].left,xp[i].right); sum--; } } edgenum = 0; int a,b; for(i=0; i<m; i++) { if(xp[i].op == '=') continue; a = find(xp[i].left); b = find(xp[i].right); if(a == b) { break; } if(xp[i].op == '<') { add(b,a); in[a]++; } else { add(a,b); in[b]++; } } if(i != m) { printf("CONFLICT\n"); continue; } queue<int> que; for(i=0; i<n; i++) { if(!in[i] && i == pre[i]) que.push(i); } int k; int flag = 0; while(!que.empty()) { k = que.front(); que.pop(); sum--; if(!que.empty()) { flag = 1; //break;不能退出,不然不能判断是因为缺信息还是信息不完全的原因 } for(i=head[k]; i != -1; i = lol[i].next) { in[lol[i].v]--; if(!in[lol[i].v]) que.push(lol[i].v); } } if(sum > 1)//这里不能用sum != 0, { printf("CONFLICT\n"); continue; } if(flag) printf("UNCERTAIN\n"); else printf("OK\n"); } return 0; }AC代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> using namespace std; const int maxn = 10010; struct H { int left,right; char op; }xp[20010]; struct node { int v,next; }lol[20010]; int pre[maxn],head[maxn],in[maxn],edgenum; int find(int x) { return x == pre[x] ? x : pre[x] = find(pre[x]); } void merge(int x,int y) { int a,b; a = find(x); b = find(y); if(a != b) { //pre[x] = y;这都写错。。。 pre[a] = b; } } void add(int x,int y) { lol[edgenum].v = y; lol[edgenum].next = head[x]; head[x] = edgenum++; } int main() { int n,m,i; while(scanf("%d%d",&n,&m) != EOF) { edgenum = 0; for(i=0; i<n; i++) { pre[i] = i; head[i] = -1; in[i] = 0; } int sum = n; for(i=0; i<m; i++) { scanf("%d %c %d",&xp[i].left,&xp[i].op,&xp[i].right); if(xp[i].op == '=') { merge(xp[i].left,xp[i].right); sum--; } } edgenum = 0; int a,b; for(i=0; i<m; i++) { if(xp[i].op == '=') continue; a = find(xp[i].left); b = find(xp[i].right); if(a == b) { break; } if(xp[i].op == '<') { add(b,a); in[a]++; } else { add(a,b); in[b]++; } } if(i != m) { printf("CONFLICT\n"); continue; } queue<int> que; for(i=0; i<n; i++) { if(!in[i] && i == pre[i]) que.push(i); } int k; int flag = 0; while(!que.empty()) { k = que.front(); que.pop(); sum--; if(!que.empty()) { flag = 1; //break;不能退出,不然不能判断是因为缺信息还是信息不完全的原因 } for(i=head[k]; i != -1; i = lol[i].next) { in[lol[i].v]--; if(!in[lol[i].v]) que.push(lol[i].v); } } if(sum > 0) { printf("CONFLICT\n"); continue; } if(flag) printf("UNCERTAIN\n"); else printf("OK\n"); } return 0; }
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <queue> #include <stack> #include <map> #include <cstring> #include <climits> #include <cmath> using namespace std; const int maxn = 10010; struct H { int left,right; char op; }xp[20010]; struct node { int v,next; }lol[20010]; int pre[maxn],head[maxn],in[maxn],edgenum; int find(int x) { return x == pre[x] ? x : pre[x] = find(pre[x]); } void merge(int x,int y) { int a,b; a = find(x); b = find(y); if(a != b) { //pre[x] = y;这都写错。。。 pre[a] = b; } } void add(int x,int y) { lol[edgenum].v = y; lol[edgenum].next = head[x]; head[x] = edgenum++; } int main() { int n,m,i; while(scanf("%d%d",&n,&m) != EOF) { edgenum = 0; for(i=0; i<n; i++) { pre[i] = i; head[i] = -1; in[i] = 0; } int sum = n; for(i=0; i<m; i++) { scanf("%d %c %d",&xp[i].left,&xp[i].op,&xp[i].right); if(xp[i].op == '=') { merge(xp[i].left,xp[i].right); sum--; } } edgenum = 0; int a,b; for(i=0; i<m; i++) { if(xp[i].op == '=') continue; a = find(xp[i].left); b = find(xp[i].right); if(a == b) { break; } if(xp[i].op == '<') { add(b,a); in[a]++; } else { add(a,b); in[b]++; } } if(i != m) { printf("CONFLICT\n"); continue; } queue<int> que; for(i=0; i<n; i++) { if(!in[i] && i == pre[i]) que.push(i); } int k; int flag = 0; while(!que.empty()) { k = que.front(); que.pop(); sum--; if(!que.empty()) { flag = 1; //break;不能退出,不然不能判断是因为缺信息还是信息不完全的原因 } for(i=head[k]; i != -1; i = lol[i].next) { in[lol[i].v]--; if(!in[lol[i].v]) que.push(lol[i].v); } } printf("%d\n",sum); if(sum > 0)//这里不能用sum != 0,别人>1也能过 { printf("CONFLICT\n"); continue; } if(flag) printf("UNCERTAIN\n"); else printf("OK\n"); } return 0; }