zoukankan      html  css  js  c++  java
  • bzoj3832

    拓扑排序+set

    如果我们直接记录所有路径是不行的,那么我们要降低路径的数量,于是我们把最短路径转换到边上,这样我们就只有m条路径了。

    先计算出f[i]和g[i]表示正反拓扑最长链,把所有g插到set里,然后按照拓扑序依次枚举删点,把之前加入过的边删除,删除g[u],查询最大值,然后加入后继边每条边的权值就是f[x]+g[to]+1,再加入f[u]这样我们按照拓扑序就不用加入之前删掉的边,因为我们是按照拓扑序删的,这样后面删的点肯定会影响之前的最长链,如果不影响则说明最长链已经被枚举完了,所以之前的最长链自然也受影响。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 5e5 + 5;
    int n, m, tot, ans = 0x3f3f3f3f, p;
    vector<int> G[N], rev[N];
    int in[N], a[N], f[N], g[N];
    int rd()
    {
        int x = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
        while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
        return x * f;
    } 
    multiset<int> s;
    int main() 
    {
        n = rd();
        m = rd();
        for(int i = 1; i <= m; ++i) 
        {
            int u = rd(), v = rd();
            G[u].push_back(v);
            rev[v].push_back(u);
            ++in[v];
        }       
        queue<int> q;
        for(int i = 1; i <= n; ++i) if(in[i] == 0) q.push(i);
        while(!q.empty()) 
        {
            int u = q.front();
            a[++tot] = u;
            q.pop();
            for(int i = 0; i < G[u].size(); ++i) 
            {
                int v = G[u][i];
                f[v] = max(f[v], f[u] + 1);
                if(--in[v] == 0) q.push(v);
            }
        }
        for(int i = n; i; --i) 
        {
            int u = a[i];
            for(int j = 0; j < rev[u].size(); ++j) 
            {
                int v = rev[u][j];
                g[v] = max(g[v], g[u] + 1);
            }
        }
        for(int i = 1; i <= n; ++i) s.insert(g[i]);
        for(int i = 1; i <= n; ++i) 
        {
            int u = a[i];       
            multiset<int> :: iterator it;
            it = s.find(g[u]);
            if(it != s.end()) s.erase(it);
            for(int j = 0; j < rev[u].size(); ++j) 
            {
                it = s.find(f[rev[u][j]] + g[u] + 1);
                s.erase(it);
            }
            if(!s.empty()) if(*(s.rbegin()) < ans) ans = *(s.rbegin()), p = u;
            for(int j = 0; j < G[u].size(); ++j) 
                s.insert(g[G[u][j]] + f[u] + 1);
            s.insert(f[u]);
        }
        printf("%d %d
    ", p, ans);
        return 0;
    }
    
    View Code
  • 相关阅读:
    react脚手架搭建及配置
    mac使用技巧
    nginx配置
    vue常见前端UI库
    自定义指令
    代码缩进修改
    webpack学习入门
    webpack使用extract-text-webpack-plugin打包时提示错误
    webpack未成功全局安装
    基于jQuery的AJAX实现三级联动菜单
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7911789.html
Copyright © 2011-2022 走看看