码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3832

时间:2017-11-28 20:36:14      阅读:141      评论:0      收藏:0      [点我收藏+]

标签:std   class   拓扑   one   bzoj   lap   说明   size   hid   

拓扑排序+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\n", p, ans);
    return 0;
}
View Code

 

bzoj3832

标签:std   class   拓扑   one   bzoj   lap   说明   size   hid   

原文地址:http://www.cnblogs.com/19992147orz/p/7911789.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!