Minimal Labels CodeForces - 825E 拓扑排序 贪心 [模板]

原题链接:
E. Minimal Labels

题目大意:
给出无向图
逆向拓扑排序

分析:
拓扑排序标号的一般步骤是从小往大,而从大到小时会出现状况
所以只要反向建边,反向编号即可.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
#define pb push_back

//#define LOCAL
const int mod=1e9+7;
const int MAXN =1e5+10;
vector<int> a[MAXN];
int vis[MAXN];
priority_queue<int,vector<int> > q;
int ans[MAXN];
int main() {
#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    int n,m,N;
    cin>>n>>m;
    N=n;
    for(int i=1;i<=m;i++){
        int x,y;
        cin>>x>>y;
        a[y].pb(x);
        vis[x]++;
    }
    for(int i=1;i<=n;i++){
        if(!vis[i]) q.push(i);
    }
    while(!q.empty()){
        int t=q.top();
        q.pop();
        ans[t]=N--;
        for(int i=0;i<a[t].size();i++){
            vis[a[t][i]]--;
            if(!vis[a[t][i]]) q.push(a[t][i]);
        }
    }
    for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
    cout<<endl;
    return 0;
}

PS.
正向的拓扑排序(模板):

//拓扑排序 ① 
#include <cstdio>  
#include <cstring>  
#define MAXN 517  
int G[MAXN][MAXN];//路径  
int in_degree[MAXN];//入度  
int ans[MAXN];  
int n, m, x, y;  
int i, j;  

void toposort()  
{  
    for(i = 1; i <= n; i++)  
    {  
        for(j = 1; j <= n; j++)  
        {  
            if(G[i][j])  
            {  
                in_degree[j]++;  
            }  
        }  
    }  
    for(i = 1; i <= n; i++)//从最小的开始寻找,  
    {//这样保证了有多个答案时序号小的先输出  
        int k = 1;  
        while(in_degree[k] != 0)//寻找入度为零的点  
            k++;  
        ans[i] = k;  
        in_degree[k] = -1;  
        //更新为-1,后边检测不受影响,相当于删除节点  
        for(int j = 1; j <= n; j++)  
        {  
            if(G[k][j])  
                in_degree[j]--;//相关联的入度减1  
        }  
    }  
}  

void init()  
{  
    memset(in_degree,0,sizeof(in_degree));  
    memset(ans,0,sizeof(ans));  
    memset(G,0,sizeof(G));  
}  

int main()  
{  
    while(~scanf("%d%d",&n,&m))  
    {  
        init();  
        for(i = 0; i < m; i++)  
        {  
            scanf("%d%d",&x,&y);  
            G[x][y] = 1;  
        }  
        toposort();  
        for(i = 1; i < n; i++)  
            printf("%d ",ans[i]);  
        printf("%d\n",ans[n]);  
    }  
    return 0;  
}  
//优先队列+拓扑排序
#include<iostream>  
#include<queue>  
#include<cstdio>  
#include<cstring>  
using namespace std;  
bool map[517][517];  
int in[517];  
priority_queue<int,vector<int>,greater<int> > q;  
void topo(int n)  
{  
    for(int i=1;i<=n;i++)  
    {  
        if(in[i]==0)  
            q.push(i);  
    }  
    int c=1;  
    while(!q.empty())  
    {  
        int v=q.top();  
        q.pop();  
        if(c!=n)  
        {  
            cout<<v<<" ";  
            c++;  
        }  
        else  
            cout<<v<<endl;  
        for(int i=1;i<=n;i++)  
        {  
            if(!map[v][i])  
                continue;  
            in[i]--;  
            if(!in[i])  
                q.push(i);  

        }  
    }  
}  
int main()  
{  
    int n,m,i,j;  
    while(cin>>n>>m)  
    {  
        int k=0;  
        memset(map,0,sizeof map);  
        memset(in,0,sizeof in);  
        while(m--)  
        {  
            cin>>i>>j;  
            if(map[i][j])  
                continue;  
            map[i][j]=1;  
            in[j]++;  
        }  
        topo(n);  
    }  
}  

猜你喜欢

转载自blog.csdn.net/joovo/article/details/79259261