练习赛补题-----C - Game Map dp

本文介绍了一种在图中寻找最长链的问题,并提供了两种解决方案:一种是使用拓扑排序配合动态规划,另一种则是通过深度优先搜索实现动态规划。这两种方法都能有效地找到图中满足条件的最长链。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给定一个图,在图上要求找一个最长链,使得后面一个点的度数比前一个点的度数大,问最长的长度是多少?

可以利用拓扑排序的方式进行dp,首先更新dp值全为1,然后遍历度数,每次找出最小的度数,更新完dp之后,删去这些点,再找最小的度数。。。。,最后的最大的dp值就是答案。
dp[i]代表到i点的最长的链的长度

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
const int MAXN = 1e5 + 5;

vector<int>ve[MAXN];
int deg[MAXN];
int dp[MAXN];
vector<int>ans[MAXN];

int main()
{
    int n,m;
    memset(deg,0,sizeof(deg));
    scanf("%d %d",&n,&m);
    int MIN = inf;
    for(int i = 0;i < m;++i){
        int x,y;
        scanf("%d %d",&x,&y);
        ve[x].pb(y);
        ve[y].pb(x);
        deg[x]++;deg[y]++;
    }
    int len = -1;
    for(int i = 0;i < n;++i){
        ans[deg[i]].pb(i);
        len = max(len,deg[i]);
    }
    for(int i = 0;i < n;++i){
        dp[i] = 1;
    }
    for(int i = 0;i <= len;++i){
        if(ans[i].size() > 0){
            for(int j = 0;j < ans[i].size();++j){
                int v = ans[i][j];
                for(int k = 0;k < ve[v].size();++k){
                    int p = ve[v][k];
                    if(deg[p] < deg[v])
                        dp[v] = max(dp[v],dp[p] + 1);
                }
            }
        }
    }
    int MAX = 1;
    for(int i = 0;i < n;++i){
        MAX = max(MAX,dp[i]);
    }
    printf("%d\n",MAX);
    return 0;
}


下面还有一种dp的方法,利用dfs来解决,dp[i]代表以i节点开始的最长链的长度,
dp[i] = max(dp[i],dp[k] + 1);k是i的邻接点,且度数大于i点

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
const int MAXN = 1e5 + 5;

vector<int>ve[MAXN];
int dp[MAXN];
int n,m;
int deg[MAXN];

int dfs(int id)
{
    if(dp[id]) return dp[id];
    int sum = 1;
    int len = ve[id].size();
    for(int i = 0;i < len;++i){
        int v = ve[id][i];
        if(deg[v] > deg[id]){
            sum = max(sum,dfs(v) + 1);
        }
    }
    dp[id] = sum;
    return sum;
}

int main()
{
    scanf("%d %d",&n,&m);
    memset(dp,0,sizeof(dp));
    memset(deg,0,sizeof(deg));
    for(int i = 0;i < m;++i){
        int a,b;
        scanf("%d %d",&a,&b);
        ve[a].pb(b);
        ve[b].pb(a);
        deg[a]++;deg[b]++;
    }
    int MAX = 1;
    for(int i = 0;i < n;++i){
        MAX = max(MAX,dfs(i));
    }
    printf("%d\n",MAX);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值