Finding mission [51nod 1815] [Tarjan + DP topology]

Topic Link


This question dealing with the details is really easier to ignore.

It instance, from two points on the point x S is a path, this sentence is very critical when it comes to the title.

We are very easy to think of great value should take time, but the first is the second largest value determined according to the maximum, then it must also represent the maximum value, the second largest value on this path is also on this path, can not take the maximum value of an edge, and then taking the maximum of the other side of the other, the composition of such a combination of the maximum value and the second largest value is not acceptable.

So, you inherit a maximum, we sometimes overlook the maximum value of the answer, because the point x to select when to use the maximum possible value and the second largest, behind the selected point in time point x of y, the maximum possible y is the maximum value of x to another path, but the path from x to y may form such a case the maximum value or the second largest value, so we need to consider these details.

Practice: Tarjan topology condensing point + DP

Approach is relatively easy to paste out of the mouth, but dp indeed be very fine job.

So, in order to avoid missing or guarantee is taken on the same path, we opened two dimensional dp to maintain, which is represented by a dp on the same path to reach that point over time the maximum value and the second largest value, where the maximum value for the purpose of large seq. Another two-dimensional dp, maintain that from the start, and the second largest maximum value to all of this point, that is, does not require the maximum value and the second largest on the same path.

Note, however, we are dealing here with the maximum value and the second largest value is strictly largest and second largest strictly not allowed equal.

Then, one by one we are pushed back down on it, and for this the DAG push dp, topology is the best choice.

By the way, the maximum value and the second largest deal about values, due to the strict, so we can use the first into an array, with unique deduplication this operation, relatively simple.

To a group of strong sample, it is based on two details I wrote to describe the above:

7 9 6 1
1 9 2 8 3 4 9
1 2
2 3
3 2
1 4
4 5
5 4
3 6
5 6
6 7
2 3 4 5 6 7
ans:2 2 3 3 4 8
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f3f3f3f3f
#define eps 1e-8
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 4e5 + 7;
int N, M, Q, S, a[maxN];
struct Graph
{
    int head[maxN], cnt;
    struct Eddge
    {
        int nex, to;
        Eddge(int a=-1, int b=0):nex(a), to(b) {}
    }edge[maxN * 10];
    inline void addEddge(int u, int v)
    {
        edge[cnt] = Eddge(head[u], v);
        head[u] = cnt++;
    }
    inline void clear()
    {
        cnt = 0;
        for(int i=1; i<=N; i++) head[i] = -1;
    }
} Old, Now;
int dfn[maxN] = {0}, low[maxN], tot = 0, Stap[maxN], Stop = 0, Belong[maxN], Bcnt = 0, dp[maxN][2] = {0};
bool instack[maxN] = {false};
void Tarjan(int u)
{
    dfn[u] = low[u] = ++tot;
    Stap[++Stop] = u;
    instack[u] = true;
    for(int i=Old.head[u], v; ~i; i=Old.edge[i].nex)
    {
        v = Old.edge[i].to;
        if(!dfn[v])
        {
            Tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(instack[v]) low[u] = min(low[u], dfn[v]);
    }
    if(low[u] == dfn[u])
    {
        Bcnt++;
        int v;
        do
        {
            v = Stap[Stop--];
            instack[v] = false;
            Belong[v] = Bcnt;
            if(a[v] > dp[Bcnt][0])
            {
                dp[Bcnt][1] = dp[Bcnt][0];
                dp[Bcnt][0] = a[v];
            }
            else if(a[v] < dp[Bcnt][0] && a[v] > dp[Bcnt][1]) dp[Bcnt][1] = a[v];
        } while(u ^ v);
    }
}
int du[maxN] = {0}, ans[maxN][2] = {0}, mx[maxN][2];
void tp_sort()
{
    for(int u=1; u<=N; u++)
    {
        if(!dfn[u]) continue;
        for(int i=Old.head[u], v; ~i; i=Old.edge[i].nex)
        {
            v = Old.edge[i].to;
            if(Belong[u] == Belong[v]) continue;
            Now.addEddge(Belong[u], Belong[v]);
            du[Belong[v]] ++;
        }
    }
    queue<int> Q;
    Q.push(Belong[S]);
    for(int i=1; i<=Bcnt; i++) { ans[i][0] = dp[i][0]; ans[i][1] = dp[i][1]; mx[i][0] = dp[i][0]; mx[i][1] = dp[i][1]; }
    int u, work[6] = {0}, len;
    while(!Q.empty())
    {
        u = Q.front(); Q.pop();
        for(int i=Now.head[u], v; ~i; i=Now.edge[i].nex)
        {
            v = Now.edge[i].to;
            du[v] --;
            len = 0;
            work[++len] = ans[u][0]; work[++len] = ans[u][1]; work[++len] = dp[v][0]; work[++len] = dp[v][1];
            sort(work + 1, work + len + 1);
            len = (int)(unique(work + 1, work + len + 1) - work - 1);
            if(work[len - 1] > ans[v][1])
            {
                ans[v][0] = work[len];
                ans[v][1] = work[len - 1];
            }
            if(mx[u][0] > dp[v][0])
            {
                if(ans[v][1] < dp[v][0]) { ans[v][0] = mx[u][0]; ans[v][1] = dp[v][0]; }
            }
            else if(mx[u][0] < dp[v][0])
            {
                if(mx[u][0] > dp[v][1] && mx[u][0] > ans[v][1]) ans[v][1] = mx[u][0];
            }
            else
            {
                if(mx[u][1] > dp[v][1] && mx[u][1] > ans[v][1]) ans[v][1] = mx[u][1];
            }
            len = 0;
            work[++len] = mx[u][0]; work[++len] = mx[u][1]; work[++len] = mx[v][0]; work[++len] = mx[v][1];
            sort(work + 1, work + len + 1);
            len = (int)(unique(work + 1, work + len + 1) - work - 1);
            mx[v][0] = work[len]; mx[v][1] = work[len - 1];
            if(!du[v]) Q.push(v);
        }
    }
}
inline void init()
{
    Old.clear(); Now.clear();
}
int main()
{
    scanf("%d%d%d%d", &N, &M, &Q, &S);
    init();
    for(int i=1; i<=N; i++) scanf("%d", &a[i]);
    for(int i=1, u, v; i<=M; i++)
    {
        scanf("%d%d", &u, &v);
        Old.addEddge(u, v);
    }
    Tarjan(S);
    tp_sort();
    for(int i=1, id; i<=Q; i++)
    {
        scanf("%d", &id);
        if(!dfn[id]) printf("-1");
        else printf("%d", ans[Belong[id]][1]);
        printf(i == Q ? "\n" : " ");
    }
    return 0;
}

 

Published 886 original articles · won praise 1059 · Views 120,000 +

Guess you like

Origin blog.csdn.net/qq_41730082/article/details/105270693