当前位置: 首页 > article >正文

拓扑排序_走多远

蓝桥账户中心

拓扑排序: 用于查找先后顺序的 将最前面的定义为入度为0的点 不断遍历 拓扑排序会出现多种解

实现过程

1. 用队列存储点的先后顺序()

#include <bits/stdc++.h>

#define endl '\n'
#define maxn 1000005
#define ll long long

using namespace std;

ll dist[maxn];
vector< vector<int> > graph(maxn);
vector<int> ans;  //记录边的顺序
queue<int> q;
int deg[maxn];

void initGraph( int n) {  //初始化邻接表
    for( int i = 0; i < n; ++i ){
        graph[i].clear();
    }
}

void addEdge( int u, int v){  //添加邻边
    graph[u].push_back(v);
    ++deg[v];  //添加度
}

bool topoSort( int n){
    for ( int i = 0; i < n; ++i ){  //先找到入度为0的点
        if ( deg[i] == 0 ){
            q.push(i);
            --deg[i];
        }
    }
    while (!q.empty()){
    
	    int u = q.front();
        q.pop();
        ans.push_back(u);  //将符合条件的点加入顺序表
        for ( int i = 0; i < graph[u].size(); ++i ){
            int v = graph[u][i];
            --deg[v];
            if ( deg[v] == 0 ){  //继续查找符合条件的点
                q.push(v);
            }
        }
    }
    return ans.size() == n;
}

int main() {

    int n; cin >> n;
    int m; cin>> m;
    initGraph( n);  //初始化边

    for ( int i = 0; i < m; ++i ){
        int u; cin >> u;
        int v; cin >> v;
        addEdge( u - 1, v - 1);
    } 

    ll ret = 0; 

    if ( topoSort(n)){
        for ( int i = n - 1; i >= 0; --i ){
            int u = ans[i];
            for ( int j = 0; j < graph[u].size(); ++j ){
                int v = graph[u][j];
                dist[u] = max( dist[u], dist[v] + 1);
            }
            ret = max( ret, dist[u]);
        } 
        cout << ret << endl;
    }else{
        cout << ret << endl;
    }

    return 0;
}

但是这一题 就有点不太友好 需要自己发现隐含条件

蓝桥账户中心

因为拓扑排序适用于 有向无环图 但是这题 就只是一个案例 就是无相有环图 但是仔细观察题目 有一个 

那么就变成一个有向无环图了 

这里是代码

#include<bits/stdc++.h>

#define endl '\n'
#define maxn 100005
#define ll long long

using namespace std;

int a[maxn];
int deg[maxn];
ll dist[maxn];
vector< vector<int> > graph(maxn);
vector<int> ans;
queue<int> q;

void initGrapg(int n ){  //初始化graph
    for ( int i = 0; i < n; ++i ){
        graph[i].clear();
    }
}

void addEdge(int u, int v ){  //建边
    if ( a[u] < a[v]){  //只能去到观赏值大的
        graph[u].push_back(v);
        ++deg[v];
    }
    if ( a[v] < a[u]){
        graph[v].push_back(u);
        ++deg[u];
    }
}

void topoSort( int n){
    for ( int i = 0; i < n; ++i ){
        if ( deg[i] == 0 ){
            q.push(i);
            //--deg[i];
        }
    }
    while ( !q.empty()){
        int u = q.front();
        ans.push_back(u);
        q.pop();
        for ( int i = 0; i < graph[u].size(); ++i){
            int v = graph[u][i];
            --deg[v];
            if ( deg[v] == 0 ){
                q.push(v);
            }
        }
    }
}


int main() {

    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    int n; cin >> n;
    int m; cin >> m;

    initGrapg(n);

    for ( int i = 0; i < n; ++i ){  //输入观赏值
        cin >> a[i];
    }

    for ( int i = 0; i < m; ++i ){  //建边 
        int u; cin >> u;
        int v; cin >> v;
        addEdge(u - 1, v - 1);  //位置偏移
    }

    topoSort(n);

    ll ret = 0;

    for ( int i = n - 1; i >= 0; --i ){
    	ll tmp = 0; 
        int u = ans[i];
        for ( int j = 0; j < graph[u].size(); ++j ){
            int v = graph[u][j];
            tmp = max( tmp, dist[v]);
        }
        dist[u] = max(dist[u], tmp + a[u]);
        ret = max( ret, dist[u]); 
    }

    cout << ret << endl;

    return 0;
}

蓝桥账户中心

这一道的话其实就是有一个陷阱

刚开始的时候 我直接用like数组保存好感度 忽略了可以有不同的边到达相同的边

借着这个机会 了解了一下pair的用法

#include <bits/stdc++.h>

#define endl '\n'
#define ll long long
#define inf INT_MIN
#define maxn 200005

using namespace std;

int dp[maxn];  //代表从最开始的边开始 到达第i个点的最大好感度
vector<int> ans;
vector< vector< pair<int, int> > > graph(maxn);
queue<int> q;
int deg[maxn];

void initGraph( int n){  //初始化邻接表
    for (int i = 0; i < n; ++i ){
        graph[i].clear();
        dp[i] = inf;
        deg[i] = 0; 
    }
    dp[0] = 0;  //最开始 好感度为0
}

void addEdge( int u, int v, int w){  //添加邻边
    graph[u].push_back({v, w});
    ++deg[v];
}

void topoSort( int n ){
    for ( int i = 0; i < n; ++i ){
        if (deg[i] == 0 ){
            --deg[i];
            q.push(i);
        }
    }
    while ( !q.empty()){
        int u = q.front();
        q.pop();
        ans.push_back(u);
        for ( int i = 0; i < graph[u].size(); ++i ){
            int v = graph[u][i].first;
            --deg[v];
            if ( deg[v] == 0){
                q.push(v);
            }
        }
    }
}

int main() {

    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    int n; cin >> n;
    int m; cin >> m;

    initGraph(n);  //初始化邻接表

    for ( int i = 0; i < m; ++i ){
        int u; cin >> u;
        int v; cin >> v;
        int w; cin >> w;
        addEdge( u - 1, v - 1, w);

    }

    topoSort(n);

    int ret = 0;

    for ( int i = 0; i < n; ++i ){  //这次从前往后遍历 因为要到达终点 到达终点需要前->后
        int u = ans[i];
        for ( int j = 0; j < graph[u].size(); ++j ){
        	int v = graph[u][j].first; 
            int like = graph[u][j].second; 
            dp[v] = max( dp[v], dp[u] + like);
        }
    } 

    for ( int i = 0; i < n; ++i ){
        if (dp[i] >= 100 && graph[i].size() == 0 ){
            ++ret;
        }
    }

    cout << ret << endl;

    return 0;
}


http://www.kler.cn/a/570113.html

相关文章:

  • SQL Server下载和安装细节
  • 4.Linux操作系统命令
  • Microk8s Ingress实现七层负载均衡
  • 玩转ChatGPT:Claude 3.7 Sonnet进行数据分析(分类)
  • 如何评估大语言模型(LLMs)
  • LLM - Attention Is All You Need 的理解
  • C++ 二叉树代码
  • SQL 中为什么参数多了not in 比 in 慢多了,怎么优化
  • Linux常见操作命令
  • AI 赋能 RPA:一键生成热点话题文章的奥秘
  • c++ accumulate、find、count、fill、fill_n、copy、sort、unique 泛型算法
  • 【实战篇】【深度解析DeepSeek:从机器学习到深度学习的全场景落地指南】
  • 算法-回溯篇02-组合总和 III
  • LeetCode hot 100—矩阵置零
  • Python:全方位赋能,开启科技前沿无限可能
  • Ubuntu20.04 ros-noetic下opencv多版本问题may conflict with libopencv_highgui.so.4.2
  • 鸿蒙NEXT开发-华为账号服务
  • MATLAB CVX 能处理的目标函数数量级极限是多少?
  • 【后端】Flask vs Django vs Node.js 对比分析
  • 数据结构——哈希表的实现