[Summary] topological sorting


I, on the topological sorting

1. Definitions

For any of the DAG (Directed Acyclic Graph, directed acyclic graph), if a sequence a of FIG all the nodes, and for any one side \ ((U, V) \) , U position in the sequence are v position before, we call such a sequence for the sequence topology map (topological order), seeking topological order process is called topological sorting (topological Sort).

2. implementation process

We will each drawing into 0 degree node enqueued from the queue in each node in extensions, each extension of the adjacent dots to minus 1. If the adjacent nodes to expand into is 0, then we have this node into the team.

Second, the application of topological sorting

Topological sorting can solve any kind of problem?

1. whether there is a loop in FIG.

If there FIG ring, then after the topological sort, the ring of a certain node is not 0, and these nodes can not be inserted into the queue.
According to this we can determine the nature of the ring.

void topo_sort(){
    queue<int> q;
    for(int i=1;i<=n;i++){
        if(!in[i]) q.push(i);
    }
    while(!q.empty()){
        int u=q.front();q.pop();
        ans[++cnt]=u;
        for(int e=first[u];e;e=next[e]){
            int v=go[e];
            if(!--in[v]) q.push(v);
        }
    }
}
//在main函数内 
if(cnt!=n) printf("exist");
for(int i=1;i<=n;i++) if(!ans[i]) printf("exist");
//两种判环方式 

2. Describe the relationship between the elements

Example. 1: P1113 chores

Entry title. Only after all the debris will be completed before the beginning of this one debris, and the debris completion time is determined by the maximum time spent debris.
As long as each update of the maximum time on it.

#include<bits/stdc++.h>
#define N 100100
using namespace std;
int in[N],cost[N],dist[N];
int n,first[N],next[N],go[N],tot;
inline void add_edge(int u,int v){
    next[++tot]=first[u];
    first[u]=tot;
    go[tot]=v;
}
inline void toposort(){
    queue<int> q;
    for(int i=1;i<=n;i++){
        if(!in[i]) q.push(i);
        dist[i]=max(dist[i],cost[i]);
    }
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int e=first[u];e;e=next[e]){
            int v=go[e],w=cost[v];
            in[v]--;
            dist[v]=max(dist[v],dist[u]+w);
            if(!in[v]) q.push(v);
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1,id,len,must;i<=n;i++){
        scanf("%d%d",&id,&len);
        cost[id]=len;
        while(scanf("%d",&must)&&must){
            add_edge(must,id);
            in[id]++;
        }
    }
    toposort();
    int ans=0;
    for(int i=1;i<=n;i++) ans=max(ans,dist[i]);
    printf("%d",ans);
    return 0;
}

Example 2: P3116 [USACO15JAN] appointment Meeting Time

+ Topological sort of dynamic programming, the subject requires a minimum time is obtained from a common starting point to the end point n, 1. So we can start topological sorting 1 from the point when a node u v, can spend cb[e], ce[e]time of u to v. Dynamic transfer equation if(f[u][i]) f[v][i+cb[e](ce[e])]=1. Where f represents the node i can reach u takes time.
But the degree of node 0 is not necessarily the only one, when there is no other penetration node 0, there is some nodes will not be into the team. At this point we first need to make only one other topological sorting, thus ensuring that only 1-degree zero.

#include<bits/stdc++.h>
using namespace std;
int n,m,tot,in[100010];
int first[100010],next[100010],go[100010],cb[100010],ce[100010];
int stb[110][20010],ste[110][20010];
inline void add_edge(int u,int v,int c,int d){
    next[++tot]=first[u];
    first[u]=tot;
    go[tot]=v;
    cb[tot]=c;ce[tot]=d;
}
inline void Deal_first(){
    queue<int>q;
    for(int i=2;i<=n;i++) if(in[i]==0) q.push(i);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int e=first[u];e;e=next[e]){
            int v=go[e];
            if(!--in[v]) q.push(v);
        }
    }
}
inline void Topo_sort(){
    queue<int> q;
    q.push(1);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int e=first[u];e;e=next[e]){
            int v=go[e];
            if(!--in[v]) q.push(v);
            for(int i=0;i<=10001;i++){//动态规划
                if(stb[u][i]) stb[v][i+cb[e]]=1;
                if(ste[u][i]) ste[v][i+ce[e]]=1;
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,u,v,c,d;i<=m;i++){
        scanf("%d%d%d%d",&u,&v,&c,&d);
        add_edge(u,v,c,d);
        in[v]++;
    }
    Deal_first();
    stb[1][0]=ste[1][0]=1;
    Topo_sort();
    for(int i=0;i<=10000;i++){
        if(stb[n][i]&&ste[n][i]){
            printf("%d",i);
            return 0;
        }
    }
    printf("IMPOSSIBLE");
    return 0;
}

Example. 3: P3243 [HNOI2015] of dishes,

This appears to be a purely topological sorting problem. As long as we maintain it with a small stack root, each taking the smallest number of dishes to update other dishes not on it yet? Well, just look at the label is purple question you will find things are not so simple. In fact, we can easily counter example:
\ [Condition <5,1>, <3,4> \]
start only 3,5 0-degree, so that first take 3, 4 then enqueued in the queue at this time to {4,5};
will turn 4 taken after 5, and finally taken out. This gave the order (3,4,5,1), obviously the answer is (5,1,3,4).
The reason is that the subject requires to ensure required number in the order of smaller conditions ahead of the point, the optimal strategy is to make this time as large numbers at the back. Therefore, we can create an anti FIG, each queue to update the largest sequence number taken to assure that each serial number smaller top surface. In addition to a number of subject data is read, remember every time initialization.

#include<bits/stdc++.h>
#define N 100010 
using namespace std;
int t,m,n,tot,flag,in[N],ans[N];
int first[N],next[N],go[N],cnt;
inline void add_edge(int u,int v){
    next[++tot]=first[u];
    first[u]=tot;
    go[tot]=v;
}
inline void toposort(){
    priority_queue<int> q;
    for(int i=1;i<=n;i++) if(!in[i]) q.push(i);
    while(!q.empty()){
        int u=q.top();q.pop();
        ans[++cnt]=u;
        for(int e=first[u];e;e=next[e]){
            int v=go[e];
            in[v]--;
            if(!in[v]) q.push(v);
        }
    }
}
inline void clear_data(){
    tot=0;flag=0;cnt=0;
    memset(first,0,sizeof(first));
    memset(next,0,sizeof(next));
    memset(go,0,sizeof(go));
    memset(in,0,sizeof(in));
    memset(ans,0,sizeof(ans));
}
int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        clear_data();
        for(int i=1,u,v;i<=m;i++){
            scanf("%d%d",&u,&v);
            in[u]++;
            add_edge(v,u);
        }
        toposort();
        if(cnt<n) printf("Impossible!\n");
        else{
            for(int i=cnt;i>=1;i--) printf("%d ",ans[i]);
            printf("\n");
        }
    }
    return 0;
}

Example. 4: P1983 grading station

Find the minimum number of questions asked to grade division. Trains stop only at the level of greater than has been ported station, so the docking station point undocked station (small level of large point level). The DAG FIG calculated from the number of layers is the topological sort answer.

#include<bits/stdc++.h>
#define N 1020
using namespace std;
int n,m,h[N],vis[N],link[N][N],in[N];
int q[N],tot,ans,p;
inline void toposort(){
    memset(vis,0,sizeof(vis));
    do{//求DAG的层数
        p=0;//p为节点度数为0的个数
        for(int i=1;i<=n;i++) if(!in[i]&&!vis[i]) q[++p]=i,vis[i]=1;
        for(int i=1;i<=p;i++)
            for(int j=1;j<=n;j++)
                if(link[q[i]][j]) in[j]--,link[q[i]][j]=0;
        ans++;//不断累积层数
    }while(p>0);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,s;i<=m;i++){
        scanf("%d",&s);
        memset(vis,0,sizeof(vis));
        for(int j=1;j<=s;j++){
            scanf("%d",&h[j]);
            vis[h[j]]=1;
        }
        for(int j=h[1];j<=h[s];j++){//枚举所有列车可能经过的节点
            if(!vis[j])//不停靠的节点
                for(int k=1;k<=s;k++){
                    if(!link[j][h[k]]){//建立关系
                        in[h[k]]++,link[j][h[k]]=1;
                    }
                }
        }
    }
    toposort();
    printf("%d",ans-1);
    return 0;
}

Guess you like

Origin www.cnblogs.com/cyanigence-oi/p/11746085.html