P1347 排序(拓扑排序)
这个题是我照着题解一点点理解一点点打出来的。
拓扑排序:
定义:将有向图中的顶点以线性方式进行排序。即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点v的前面。
确定一个图的拓扑排序是基于bfs的,bfs是基于队列的。
首先记录所有的点和所有点的入度(在连边时顺便求得的入度),
if(vis[aa]!=1) vis[aa]=1,tot++;//tot记录的是目前能算得上点(因为是随读随做)
if(vis[cc]!=1) vis[cc]=1,tot++;
son[aa].push_back(cc);//连边 du[cc]++;//顺便求入度
因为每次读入数去topsort都要用到入度,所以用一个别的数组复制一遍。如果存在两个入度为0的点,则不知道该谁先谁后。则构不成拓扑序。
要是能构成的话,还需要别的边,所以是缺边,条件不足
if(!vv) vv=true; else uu=true;
没有入度为0的点则代表有环。出现矛盾。
具体的看代码吧
#include <iostream> #include <cstdio> #include <vector> #include <queue> #include <cstring> using namespace std; vector <int> son[29]; int uu,sum,duu[29],du[29],vv,p[29],vis[29],inn[29],tot,n,m,ans=-1; queue <int> q; char a,b,c; bool flag; int topsort(){ uu=false;vv=false;sum=0; memset(p,0,sizeof(p)); for(int i=1;i<=26;i++){ duu[i]=du[i]; if(!duu[i]&&vis[i]){ if(!vv) vv=true; else uu=true; q.push(i); p[++sum]=i; } } if(q.empty()) return 1; while(!q.empty()){ int u=q.front();vv=false;q.pop(); for(int i=0;i<son[u].size();i++){ duu[son[u][i]]--; if(duu[son[u][i]]==0){ q.push(son[u][i]); if(!vv) vv=true; else uu=true; p[++sum]=son[u][i]; } } } if(sum!=tot) return 1; if(uu==true) return 2; return 0; } int main(){ cin>>n>>m; for(int i=1;i<=m;i++){ cin>>a>>b>>c; int aa=a-64,cc=c-64; if(vis[aa]!=1) vis[aa]=1,tot++; if(vis[cc]!=1) vis[cc]=1,tot++; son[aa].push_back(cc); du[cc]++; if(flag==0) ans=topsort(); if(ans==1&&flag==0){ printf("Inconsistency found after %d relations.",i); flag=1; } if(sum==n&&ans==0&&flag==0){ printf("Sorted sequence determined after %d relations: ",i); for(int j=1;j<=n;j++) printf("%c",p[j]+64); printf("."); flag=1; } } if(flag==0) printf("Sorted sequence cannot be determined."); return 0; }