拓扑排序例题

不懂的看这里

拓扑排序

以下是例题:

拓扑排序·一

简单拓扑判环

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
vector<int> G[maxn];
int inDeg[maxn];
int n,m;
queue<int>q;
int sum;
bool top(){
while(!q.empty()) q.pop();
sum = 0;


for(int  i = 1;i <= n ; i++) if(!inDeg[i]) q.push(i);
while(!q.empty()){
    int to = q.front();
    q.pop();
    sum ++;
    for(int  i = 0; i < G[to].size(); i++){
        int edge = G[to][i];
        inDeg[edge] --;
        if(!inDeg[edge]) q.push(edge);
    }

}
if(sum == n) return 1;
else return 0;
}


int main(){
   // int n ;
   int t;
    cin >> t ;
    while(t--){
    cin >> n;
    cin >> m;
    memset(G,0,sizeof(G));
    memset(inDeg,0,sizeof(inDeg));
    for(int i  =1;i <= m ; i++) {
        int u , v;
        cin >> u >> v;
        G[u].push_back(v);
        inDeg[v]++;
    }
    if(top()) cout << "Correct" << endl;
    else cout << "Wrong" << endl;
    }
    return 0;

}

Legal or Not

同上,注意0 ~ n-1

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
const int mod = 142857;
vector<int> G[maxn];
int virus[maxn];
int inDeg[maxn];
int n,m;
int sum = 0;
queue<int>q;

bool topsort(){
    while(!q.empty()) q.pop();
    sum = 0;


    for(int  i = 0;i < n ; i++) if(!inDeg[i]) q.push(i);
        while(!q.empty()){
            int to = q.front();
            q.pop();
            sum ++;
            for(int  i = 0; i < G[to].size(); i++){
                int edge = G[to][i];
                inDeg[edge] --;
                if(!inDeg[edge]) q.push(edge);
      //  virus[edge] = (virus[edge] + virus[to]) % mod;
            }

        }
        if(sum == n)return 1;
        else return 0;
    }


    int main(){
   // int n ;

        int k ;

        while(cin >> n){
            cin >> m;
            if(!n&&!m) break;
   // cin >> k;
    //memset(virus, 0 , sizeof virus);
    //int x;
    //for(int i = 1; i <= k ; i++) cin >> x,virus[x] ++;
            memset(G,0,sizeof(G));
            memset(inDeg,0,sizeof(inDeg));
            for(int i  =1;i <= m ; i++) {
                int u , v;
                cin >> u >> v;
                G[u].push_back(v);
                inDeg[v]++;
            }
            if(topsort()) 
                puts("YES");
            else 
    puts("NO");    //int sum = 0;
    //for(int i = 1; i <= n; i++) sum = (sum + virus[i] ) % mod;
    //cout << sum << endl;
}
return 0;

}

拓扑排序·二
拓扑排序的应用

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
const int mod = 142857;
vector<int> G[maxn];
int virus[maxn];
int inDeg[maxn];
int n,m;
queue<int>q;

void topsort(){
while(!q.empty()) q.pop();
//sum = 0;


for(int  i = 1;i <= n ; i++) if(!inDeg[i]) q.push(i);
while(!q.empty()){
    int to = q.front();
    q.pop();
    //sum ++;
    for(int  i = 0; i < G[to].size(); i++){
        int edge = G[to][i];
        inDeg[edge] --;
        if(!inDeg[edge]) q.push(edge);
        virus[edge] = (virus[edge] + virus[to]) % mod;
    }

}

}


int main(){
   // int n ;

    int k ;

    while(cin >> n){
    cin >> m;
    cin >> k;
    memset(virus, 0 , sizeof virus);
    int x;
    for(int i = 1; i <= k ; i++) cin >> x,virus[x] ++;
    memset(G,0,sizeof(G));
    memset(inDeg,0,sizeof(inDeg));
    for(int i  =1;i <= m ; i++) {
        int u , v;
        cin >> u >> v;
        G[u].push_back(v);
        inDeg[v]++;
    }
    topsort();
    int sum = 0;
    for(int i = 1; i <= n; i++) sum = (sum + virus[i] ) % mod;
    cout << sum << endl;
    }
    return 0;

}

Skiing

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
int n , m;
vector<pair<int,int> >G[maxn];
int inDeg[maxn];
int dp[maxn];
void topsort(){
queue<int>q;
while(!q.empty())q.pop();
for(int i = 1; i <= n ; i++) if(!inDeg[i]) q.push(i);
while(!q.empty()){
    int now = q.front();
    q.pop();
    for(int i = 0; i < G[now].size(); i++){
        int to = G[now][i].first;
        inDeg[to]--;
        if(!inDeg[to]) q.push(to);
        dp[to] = max(dp[to],dp[now] + G[now][i].second);
    }

}

}

int main(){
int t;
ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);
cin >> t;
while(t--){
    cin >> n >> m;
    memset(inDeg,0,sizeof inDeg);
    memset(dp,0,sizeof dp);
    for(int i = 1;i <= n ; i++) G[i].clear();
    while(m--){
        int u , v, w;
        cin >> u >> v >> w;
        G[u].push_back(make_pair(v,w));
        //G[v].push_back(make_pair((u,w)));
        inDeg[v] ++;
    }
    topsort();
    int maxx = 0;
    for(int i  =1; i <= n ; i++) maxx = max(dp[i],maxx);
    cout << maxx << endl;
}
return 0;
}

Almost Acyclic Graph

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
int n , m;
int inDeg[maxn],ruDeg[maxn];
std::vector<int> v[maxn];
bool topsort(){
	int sum = 0;
	queue<int>q;
	while(!q.empty()) q.pop();
	for(int i = 1; i <= n ; i++){
		if(!inDeg[i]) q.push(i);
	}
	while(!q.empty()){
		int now = q.front();
		q.pop();
		sum ++;
		for(int i = 0; i < v[now].size(); i++){
			int to = v[now][i];
			if(--inDeg[to] == 0){
				q.push(to);
			}
		}
	}
	if(sum == n) return 1;
	else return 0;
}

int main(){
	cin >> n >> m;
	for(int i  = 1; i <= m ; i++){
		int u , w;
		cin >> u >> w;
		v[u].push_back(w);
		inDeg[w]++;
		ruDeg[w]++;
	}
	//topsort();
	if(topsort() == 1){
		cout << "YES" << "\n" ;
	}
	else {
		bool flag = 0;
		for(int i = 1; i <= n; i++){
			memcpy(inDeg,ruDeg,sizeof ruDeg);
			if(inDeg[i] >= 1){
				inDeg[i] --;
				if(topsort() == 1){
					flag = 1;
					cout << "YES" << "\n";
					break;
				}
			}
		}
		if(!flag) puts("NO");
	}
	return 0;
}

确定比赛名次

优先队列 + 拓扑(字典序)

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
int n, m;
vector<int>G[maxn];
int inDeg[maxn];
int dp[maxn];
int cnt;
int mp[1000][1000];
void topsort()
{
	priority_queue<int,vector<int>,greater<int> >q;
    //queue<int>q;
    cnt = 0;
    while(!q.empty())q.pop();
    for(int i = 1; i <= n ; i++) if(!inDeg[i]) q.push(i);
    while(!q.empty())
    {
        int now = q.top();
        q.pop();
        dp[cnt++] = now;
        for(int i = 0; i < G[now].size(); i++)
        {
            int to = G[now][i];
            inDeg[to]--;
            if(!inDeg[to]) q.push(to);
        //    dp[to] = max(dp[to],dp[now] + G[now][i].second);
        }

    }

}

int main()
{
    int t;
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
  //  cin >> t;
   
        while(cin >> n >> m){
		
        memset(inDeg,0,sizeof inDeg);
        memset(dp,0,sizeof dp);
        for(int i = 1; i <= n ; i++) G[i].clear();
        while(m--)
        {
            int u, v, w;
            cin >> u >> v ;
            
            //if(mp[u][v] == 0)
            G[u].push_back(v);
            
            //G[v].push_back(make_pair((u,w)));
            inDeg[v] ++;
        }
        topsort();
        //int maxx = 0;
        for(int i  = 0; i < cnt ; i++)
        printf("%d%c",dp[i]," \n"[i == cnt -1]);
    }
    return 0;
}

逃生

举个例子如图:

在这里插入图片描述

如果你用优先队列拓扑排序得到的是:3 5 6 4 1 7 8 9 2 0

但是正确答案为 6 4 1 3 9 2 5 7 8 0 这样使得小的(1)尽量在前面。

这里我们可以得到 前面的小的不一定排在前面,但是有一点后面大的一定排在后面。

我们看 6和3不一定3排在前面,因为6后面连了一个更小的数字1能使得6更往前排。

在看 2和 8,8一定排在后面,因为8后面已经没有东西能使它更往前排(除了0)。

所以最后我们的做法就是 建立一个反图,跑一边字典序最大的拓扑排序,最后再把这个排序倒过来就是答案了。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 7;
int n, m;
vector<int>G[maxn];
int inDeg[maxn];
int dp[maxn];
int cnt;
void topsort()
{
    priority_queue<int> q;
    //queue<int>q;
     cnt = 0;
    while(!q.empty())q.pop();
    for(int i = 1; i <= n ; i++) if(!inDeg[i]) q.push(i);
    while(!q.empty())
    {
        int now = q.top();
        q.pop();
        dp[cnt++] = now;
        for(int i = 0; i < G[now].size(); i++)
        {
            int to = G[now][i];
            inDeg[to]--;
            if(!inDeg[to]) q.push(to);
        //    dp[to] = max(dp[to],dp[now] + G[now][i].second);
        }

    }

}

int main()
{
    int t;
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> t;
    while(t--)
    {
        cin >> n >> m;
        memset(inDeg,0,sizeof inDeg);
        memset(dp,0,sizeof dp);
        for(int i = 1; i <= n ; i++) G[i].clear();
        while(m--)
        {
            int u, v, w;
            cin >> u >> v ;
            G[v].push_back(u);
            //G[v].push_back(make_pair((u,w)));
            inDeg[u] ++;
        }
        topsort();
        //int maxx = 0;
        for(int i  = cnt - 1; i >= 0 ; i--)
        printf("%d%c",dp[i]," \n"[i == 0]);
    }
    return 0;
}

Labeling Balls
优先队列 + 反向拓扑

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int maxn = 1e5 + 7;
int n, m;
vector<int>G[maxn];
int inDeg[maxn];
int dp[maxn];
int cnt;
int sum ,ans ;
int mp[1000][1000];
bool topsort()
{
	//queue<int>q;
	priority_queue<int>q;
    //queue<int>q;
    cnt = 0;
    sum = 0;
    while(!q.empty())q.pop();
    for(int i = 1; i <= n ; i++) if(!inDeg[i]) q.push(i);
    while(!q.empty())
    {
        int now = q.top();
        q.pop();
      //  cout << now << endl;
      sum ++;
        dp[now] = n--;
      //  cout << dp[now] << endl;
        for(int i = 0; i < G[now].size(); i++)
        {
            int to = G[now][i];
            inDeg[to]--;
            if(!inDeg[to]) q.push(to);
        //    dp[to] = max(dp[to],dp[now] + G[now][i].second);
        }

    }
if(sum == ans)return 1;
else return 0;
}

int main()
{
    int t;
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
  //  cin >> t;
     cin >> t;
     while(t--){
	 
        cin >> n >> m;
		ans = n;
        memset(inDeg,0,sizeof inDeg);
        memset(dp,0,sizeof dp);
        for(int i = 1; i <= n ; i++) G[i].clear();
        while(m--)
        {
            int u, v, w;
            cin >> u >> v ;
            
            //if(mp[u][v] == 0)
            G[v].push_back(u);
            
            //G[v].push_back(make_pair((u,w)));
            inDeg[u] ++;
        }
        if(topsort())
        //int maxx = 0;
        for(int i  = 1; i <= ans ; i++)
        printf("%d%c",dp[i]," \n"[i == ans]);
        else 
        puts("-1");
    }
    return 0;
}
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页