当前位置: 代码迷 >> 综合 >> 拓扑排序 hdu1811 Rank of Tetris
  详细解决方案

拓扑排序 hdu1811 Rank of Tetris

热度:87   发布时间:2023-12-14 04:14:31.0

这题有3个方面值得深思

1.=的处理,读入的时候就先考虑=的,用并查集合并,把第二个节点完全用第一个节点代替,后面建图的时候都使用的是并查集的根节点即可

2.判断是否是唯一确定的,就看队列中的size是否永远<=1,若出现>=2,则说明同时有两个点的入度为0,就不能唯一确定

3.判断是否有冲突,先记录并查集后,有多少个连通块,记为sum,然后再判断队列中一共运行了多少个点,记为cnt,若cnt等于sum,那么就没冲突,否则就有冲突,因为如果存在环,那么必然那整个环上的任意一点的入度都会大于0,所以,这个环的节点永远不会进入队列


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<iostream>
#include<functional>
#include<algorithm>using namespace std;
typedef long long LL;const int mod=142857;
const int MX=10000+5;
const int INF=0x3f3f3f3f;int rear=0;
int vis[MX],IN[MX],P[MX];
vector<int>G[MX];int find(int x){return P[x]==x?x:(P[x]=find(P[x]));
}void Union(int u,int v){int p1=find(u),p2=find(v);P[p1]=p2;
}struct Edge{int u,v;
}E[2*MX];int main(){int n,m;while(~scanf("%d%d",&n,&m)){rear=0;memset(IN,0,sizeof(IN));memset(vis,0,sizeof(vis));for(int i=0;i<n;i++){G[i].clear();P[i]=i;}for(int i=1;i<=m;i++){int u,v;char op[10];scanf("%d%s%d",&u,op,&v);if(op[0]=='<'){E[++rear].u=u;E[rear].v=v;}else if(op[0]=='>'){E[++rear].u=v;E[rear].v=u;}else Union(u,v);}int sign=0;for(int i=1;i<=rear;i++){int p1=find(E[i].u),p2=find(E[i].v);G[p1].push_back(p2);IN[p2]++;}int cnt=0,sum=0;for(int i=0;i<n;i++) vis[find(i)]=1;for(int i=0;i<n;i++) sum+=vis[i];queue<int>work;for(int i=0;i<n;i++){if(vis[i]&&!IN[i]){work.push(i);}}while(!work.empty()){if(work.size()>=2) sign=2;int u=work.front();work.pop();cnt++;for(int i=0;i<G[u].size();i++){int v=G[u][i];IN[v]--;if(!IN[v]) work.push(v);}}if(cnt!=sum) sign=1;printf("%s\n",sign==0?"OK":(sign==1?"CONFLICT":"UNCERTAIN"));}return 0;
}


  相关解决方案