zoukankan      html  css  js  c++  java
  • 拓扑排序

    问题1.判断有没有环

    http://hihocoder.com/problemset/problem/1174

    用vector模拟邻接表,开一个记录入度的一维数组,一个存储入度为0的队列

    ac代码如下

    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<string.h>
    using namespace std;
    typedef long long int ll;
    int n,k,a,b,t,m;
    const int maxn=1e5+5;
    vector<int>v[maxn];
    queue<int>q;
    int indge[maxn];
    bool judge()
    {
        int num=0;
        while(!q.empty())q.pop();
        for(int i=1;i<=n;i++){
            if(!indge[i])q.push(i);
        }
        while(!q.empty()){
            int tot=q.front();
            q.pop();
            num++;
            for(int i=0;i<v[tot].size();i++){
                if(--indge[v[tot][i]]==0)q.push(v[tot][i]);
            }
        }
        if(num==n)return true;
        else return false;
    }
    int main()
    {
        cin>>t;
        for(int i=1;i<=t;i++){
            cin>>n>>m;
            for(int i=0;i<maxn;i++)v[i].clear();
            memset(indge,0,sizeof(indge));
            for(int j=0;j<m;j++){
                cin>>a>>b;
                v[a].push_back(b);
                indge[b]++;
            }
            if(judge())puts("Correct");
            else puts("Wrong");
        }
        return 0;
    }
    /*
    2
    2 2
    1 2
    2 1
    3 2
    1 2
    1 3
    */

     问题2:给定一个dag图,给定一些点病毒为1,他们为传染给后继结点,依次类推,求最终的病毒数量

    http://hihocoder.com/problemset/problem/1175

    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<string.h>
    using namespace std;
    typedef long long int ll;
    int n,k,m,b,t1,t2;
    const int maxn=1e5+5;
    const int mod=142857;
    vector<int>v[maxn];
    vector<ll>a(maxn);
    queue<int>q;
    int indge[maxn];
    void res()
    {
        while(!q.empty())q.pop();
        for(int i=1;i<=n;i++){
            if(!indge[i])q.push(i);
        }
        while(!q.empty()){
            int tot=q.front();
            q.pop();
            for(int i=0;i<v[tot].size();i++){
                    a[v[tot][i]]=(a[v[tot][i]]+a[tot])%mod;
                if(--indge[v[tot][i]]==0){
                    q.push(v[tot][i]);
                }
            }
        }
    }
    int main()
    {
        for(int i=0;i<maxn;i++)v[i].clear();a.clear();
        cin>>n>>m>>k;
        for(int i=0;i<k;i++){
            cin>>b;
            a[b]=1;
        }
            memset(indge,0,sizeof(indge));
            for(int j=0;j<m;j++){
                cin>>t1>>t2;
                v[t1].push_back(t2);
                indge[t2]++;
            }
            res();
        long long int ans=0;
        for(int i=1;i<=n;i++){
            ans=(ans+a[i])%mod;//;
        }
        cout<<ans<<endl;
        return 0;
    }
    /*
    2
    2 2
    1 2
    2 1
    3 2
    1 2
    1 3
    */

     洛谷 P4017 最大食物链计数

    https://www.luogu.com.cn/problem/P4017

    题目是找生产者到最高级消费者的路线有几条。

    其实是找入度为0的点到出度为0的路径方式有几种。

    预处理入度和出度,拓扑排序,把出度为0的点的路线累加。

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<map>
    #include<string.h>
    using namespace std;
    typedef long long int ll;
    int n,k,m,b,t,t1,t2,t3,maxx=0;
    const int maxn=1e5+5;
    const int mod= 80112002;
    vector<int >v[maxn];
    vector<int>a(maxn);
    queue<int>q;
    int indge[maxn];
    int outdge[maxn];
    void topsort()
    {
        int num=0;
        while(!q.empty())q.pop();
        for(int i=1;i<=n;i++){
            if(!indge[i]){
                a[i]=1;
                q.push(i);
            }
        }
        while(!q.empty()){
            int tot=q.front();
            q.pop();
            num++;
            for(int i=0;i<v[tot].size();i++){
                if(--indge[v[tot][i]]==0){
                    q.push(v[tot][i]);
    
                }
                a[v[tot][i]]=(a[v[tot][i]]+a[tot])%mod;
            }
        }
    }
    int main()
    {
            scanf("%d%d",&n,&m);
            for(int i=0;i<maxn;i++)v[i].clear();a.clear();
            memset(indge,0,sizeof(indge));
            memset(outdge,0,sizeof(outdge));
            for(int j=0;j<m;j++){
                //cin>>t1>>t2>>t3;
                scanf("%d%d",&t1,&t2);
                v[t1].push_back(t2);
                indge[t2]++;
                outdge[t1]++;
            }
            topsort();
            int ans=0;
            for(int i=1;i<=n;i++){
                if(outdge[i]==0)ans=(ans+a[i])%mod;
            }
            cout<<ans<<endl;
            return 0;
    }

     洛谷 P1807 最长路

    https://www.luogu.com.cn/problem/P1807

    一道裸的dag拓扑排序加上了权值,vector模拟邻接表存出边和权值,dp数组更新最长路。

    /*
     展开
    题目描述
    
    设 G 为有 n 个顶点的带权有向无环图,G 中各顶点的编号为 1 到 n,请设计算法,计算图 GG 中 <1,n><1,n> 间的最长路径。
    
    输入格式
    
    输入的第一行有两个整数,分别代表图的点数 n 和边数 m。
    
    第 2 到第 (m+1) 行,每行 3 个整数 u, v,w,代表存在一条从 u 到 v 边权为w的边。
    
    输出格式
    
    输出一行一个整数,代表 1 到 n 的最长路。
    
    若 1 与 n 不联通,请输出 -1。
    */
    
    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e4+5;
    int indge[maxn],dp[maxn],bj[maxn];
    int n,m;
    vector<pair<int,int> >v[maxn];
    void topsort()
    {
        queue<int>q;
        while(!q.empty())q.pop();
        for(int i=1;i<=n;i++){
            if(!indge[i])q.push(i);
        }
        while(!q.empty()){
            int k=q.front();q.pop();
            for(int i=0;i<v[k].size();i++){
                if(--indge[v[k][i].first]==0)q.push(v[k][i].first);
                if(bj[k]){
                    dp[v[k][i].first]=max(dp[v[k][i].first],dp[k]+v[k][i].second);///自身的长度与父亲节点的最长路加上父亲到儿子这条边的长度比较
                    bj[v[k][i].first]=1;
                 }
            }
        }
    }
    int main()
    {
        cin>>n>>m;
        int a,b,c;
        memset(indge,0,sizeof(indge));
        memset(dp,0,sizeof(dp));
        memset(bj,0,sizeof(bj));
        for(int i=0;i<m;i++){
            cin>>a>>b>>c;
            v[a].push_back(make_pair(b,c));
            indge[b]++;
        }
        dp[n]=-1,bj[1]=1;///初始化dp[n]=-1,输出方便,bj[1]=1,标记1能到达点
        topsort();
        cout<<dp[n]<<endl;
        return 0;
    }
  • 相关阅读:
    深度剖析Reges.Match
    Python入门(一)
    SQL Server部分锁说明理解
    虚拟机Linux安装redis(一)
    transform matrix阅读后的理解
    小程序SKU规格选择
    React 学习记录(二)
    React 学习记录(一)
    在MVC里面使用Response.Redirect方法后记得返回EmptyResult——转载自PowerCoder
    Nodejs的安装随笔
  • 原文地址:https://www.cnblogs.com/mohari/p/12895925.html
Copyright © 2011-2022 走看看