洛谷P1347 排序(图论,拓扑排序

洛谷P1347 排序(图论,拓扑排序
蒟蒻觉得这题巨难!!!
暴风哭泣.jpg
wu~~~~
在这题之前先看一下什么是拓扑排序:
以下引自dalao的博客:

在一个有向图中,对所有的节点进行排序,要求没有一个节点指向它前面的节点。

先统计所有节点的入度,对于入度为0的节点就可以分离出来,然后把这个节点指向的节点的入度减一。

一直做改操作,直到所有的节点都被分离出来。

如果最后不存在入度为0的节点,那就说明有环,不存在拓扑排序,也就是很多题目的无解的情况。
在这里插入图片描述

以下代码时间复杂度O(V+E)。

        queue<int>q;
        vector<int>edge[n];
        for(int i=0;i<n;i++)  //n  节点的总数
            if(in[i]==0) q.push(i);  //将入度为0的点入队列
        vector<int>ans;   //ans 为拓扑序列
        while(!q.empty())
        {
            int p=q.front(); q.pop(); // 选一个入度为0的点,出队列
            ans.push_back(p);
            for(int i=0;i<edge[p].size();i++)
            {
                int y=edge[p][i];
                in[y]--;
                if(in[y]==0)
                    q.push(y);  
            }
        }
        if(ans.size()==n)   
        {
            for(int i=0;i<ans.size();i++)
                printf( "%d ",ans[i] );
            printf("\n");
        }
        else printf("No Answer!\n");   //  ans 中的长度与n不相等,就说明无拓扑序列

博客传送门
以下为该题:
洛谷P1347
数据范围很小,咋操作都不会TLE
题目说了三种情况:

若根据前x个关系即可确定这n个元素的顺序yyy…y(如ABC),输出

Sorted sequence determined after xxx relations: yyy…y.

若根据前x个关系即发现存在矛盾(如A输出

Inconsistency found after 2 relations.

若根据这m个关系无法确定这n个元素的顺序,输出

Sorted sequence cannot be determined.

(提示:确定n个元素的顺序后即可结束程序,可以不用考虑确定顺序之后出现矛盾的情况)

第一种:有稳定拓扑排序说明拓扑排序的层数是n。那么就看最长路是否有n个节点。
第二种:成环,拓扑排序判断有没有环其实很简单,如果拓扑排序没能遍历所有的点,就说明存在一个环。
第三种:如果不是前两种就是第三种了。

细节:
一、每个节点入度的统计:
头和跟在头后面的节点分开统计。原因在代码中。

//入度的统计
    for(a=0;a<30;a++) in[a]=-1,num[a]=0;
    for(a=0;a<30;a++){
        if(s.count(a)==1&&edg[a].empty()==0){
            if(in[a]==-1) in[a]=0;//如果没有出现过头头变为0,否则不变
            l=edg[a].size();
            if(l!=0){            //edg[a]内部的数入度全部+1
                p=edg[a].begin();
                while(p!=edg[a].end()){
                    if(in[*p]==-1) in[*p]=1;
                    else in[*p]++;
                    p++;
                }
            }
        }
    }

二、最长路
如果最长路的长度等于n的值,那么就找到了,输出全部节点,结束程序。也就是第一种情况。

//拓扑排序
    for(a=0;a<30;a++) {
        if (in[a] == 0) q.push(a);
    }
    while(q.empty()==0){
        x=q.front();
        v.push_back(x);
        q.pop();
        p=edg[x].begin();
        while(p!=edg[x].end()){
            in[*p]--;//每去除一条边线,就在后继节点上记录到这个节点为止边的数量
            num[*p]=max(num[*p],num[x]+1);//dp的思想,边的数量等于原来的数量和前一个节点边的数量+1的最大值
            max1=max(max1,num[*p]);
            if(in[*p]==0)
                q.push(*p);
            p++;
        }
    }

三、用vector存每个节点所有的后继节点

喜闻乐见的全部代码:
真的自闭了好几天,我还是太弱了。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define ll long long
using namespace std;

set<int> edg[30];
set<int> s;
set<int>::iterator p;
int n,m,ti,size;


void tuopu(){
    queue<int> q;
    vector<int> v;
    int in[30],num[30];
    int a,x,l,max1=0;
    //入度的统计
    for(a=0;a<30;a++) in[a]=-1,num[a]=0;
    for(a=0;a<30;a++){
        if(s.count(a)==1&&edg[a].empty()==0){
            if(in[a]==-1) in[a]=0;//头头变为0
            l=edg[a].size();
            if(l!=0){            //edg[a]内部的数入度全部+1
                p=edg[a].begin();
                while(p!=edg[a].end()){
                    if(in[*p]==-1) in[*p]=1;
                    else in[*p]++;
                    p++;
                }
            }
        }
    }
    //拓扑排序
    for(a=0;a<30;a++) {
        if (in[a] == 0) q.push(a);
    }
    while(q.empty()==0){
        x=q.front();
        v.push_back(x);
        q.pop();
        p=edg[x].begin();
        while(p!=edg[x].end()){
            in[*p]--;
            num[*p]=max(num[*p],num[x]+1);
            max1=max(max1,num[*p]);
            if(in[*p]==0)
                q.push(*p);
            p++;
        }
    }
    if(max1==n-1) {
        printf("Sorted sequence determined after %d relations: ",ti);
        for(a=0;a<v.size();a++) cout<<(char)('A'+v[a]);
        cout<<".";
        exit(0);
    }
    if(v.size()!=size) printf("Inconsistency found after %d relations.",ti),exit(0);
}
int main(){
    string tt;
    cin>>n>>m;
    for(ti=1;ti<=m;ti++){
        cin>>tt;
        int a=tt[0]-'A',b=tt[2]-'A';
        if(a==b) printf("Inconsistency found after %d relations.",ti),exit(0);
        edg[a].insert(b);
        s.insert(a);
        s.insert(b);
        size=s.size();
        tuopu();
    }
    cout<<"Sorted sequence cannot be determined.";
}

但是看见AC还是超高兴!!!
洛谷P1347 排序(图论,拓扑排序_第1张图片

你可能感兴趣的:(洛谷P1347 排序(图论,拓扑排序)