洛谷 P1137 旅行计划 (拓扑排序+dp)

在DAG中,拓扑排序可以确定dp的顺序

把图的信息转化到一个拓扑序上

注意转移的时候要用边转移

这道题的dp是用刷表法

#include
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std;

const int MAXN = 1e5 + 10;
struct Edge{ int to, next; };
Edge e[MAXN << 1];
int head[MAXN], d[MAXN];
int topo[MAXN], dp[MAXN]; 
int n, m, cnt, tot;

void AddEdge(int from, int to)
{
    e[tot] = Edge{to, head[from]};
    head[from] = tot++;
}

void read(int& x)
{
    int f = 1; x = 0; char ch = getchar();
    while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); }
    while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
    x *= f;
}

void toposort()
{
    queue<int> q;
    _for(i, 1, n)
        if(!d[i])
            q.push(i);
    while(!q.empty())
    {
        int u = q.front(); q.pop();
        topo[++cnt] = u;
        for(int i = head[u]; ~i; i = e[i].next)
        {
            int v = e[i].to;
            if(--d[v] == 0) q.push(v);
        }
    }
}

int main()
{
    memset(head, -1, sizeof(head)); tot = 0;
    read(n); read(m);
    
    _for(i, 1, m)
    {
        int u, v; 
        read(u); read(v);
        AddEdge(u, v);
        d[v]++;
    }
    
    toposort();
    _for(i, 1, n) dp[i] = 1;
    _for(i, 1, n)
    {
        int u = topo[i];
        for(int i = head[u]; ~i; i = e[i].next)
        {
            int v = e[i].to;
            dp[v] = max(dp[v], dp[u] + 1);
        }
    }
    _for(i, 1, n) printf("%d\n", dp[i]);
    
    return 0;
}

 还可以用记忆化搜索

#include
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std;

const int MAXN = 1e5 + 10;
struct Edge{ int to, next; };
Edge e[MAXN << 1];
int head[MAXN], dp[MAXN];
int n, m, cnt, tot;

void AddEdge(int from, int to)
{
    e[tot] = Edge{to, head[from]};
    head[from] = tot++;
}

void read(int& x)
{
    int f = 1; x = 0; char ch = getchar();
    while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); }
    while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
    x *= f;
}

int dfs(int u)
{
    if(dp[u] != -1) return dp[u];
    dp[u] = 1;
    for(int i = head[u]; ~i; i = e[i].next)
    {
        int v = e[i].to;
        dp[u] = max(dp[u], dfs(v) + 1);
    }
    return dp[u];
}

int main()
{
    memset(head, -1, sizeof(head)); tot = 0;
    read(n); read(m);
    
    _for(i, 1, m)
    {
        int u, v; 
        read(u); read(v);
        AddEdge(v, u);
    }
    
    memset(dp, -1, sizeof(dp));
    _for(i, 1, n) printf("%d\n", dfs(i));
    
    return 0;
}

 

转载于:https://www.cnblogs.com/sugewud/p/9883766.html

你可能感兴趣的:(洛谷 P1137 旅行计划 (拓扑排序+dp))