DAG+dp(拓扑排序+dp)

传送门

传说中,有一个字符王国,王国里有n个城市,每个城市都将一个字符作为自己城市的象征。城市和城市之间有边相连,整个王国共有m条边(有向)。(2 <= n,m <= 300000)

我们定义一条路径的枯燥度为这条路径上出现次数最多的字符出现的次数。

现在字符王国的国王想知道,王国里最枯燥的路径的枯燥度有多大。

输入

第一行两个整数n,m表示城市数量和边数
第二行一个长为n的字符串,其中第i个字符表示编号为i的城市的代表字符
接下来m行,每行两个整数x,y,表示城市x和城市y之间有一条边

输出

一行一个整数表示王国里最枯燥的路径的枯燥度

数据范围

10% 2 <= n, m <= 15
30% 2 <= n ,m <= 1000
100% 2 <= n,m <= 300000

输入样例

5 4
abaca
1 2
1 3
3 4
4 5

输出样例

3

这个题是不用判环的题目上好像没说:
这个题是一个经典的DAG上跑dp

 

 

#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
#include<queue> 
using namespace std;
typedef long long ll;
const int maxn=3e5+100;
int dp[maxn][30]; 
char a[maxn];
vector<int>v[maxn];
int in[maxn];
int vis[maxn]; 
int n,m;
int ma=0;
int main(){
    cin>>n>>m;
    scanf("%s",a+1);
    int x,y; 
    for(int i=1;i<=m;i++){
        cin>>x>>y;
        v[x].push_back(y);
        in[y]++;
    }
    queue<int>q;
    for(int i=1;i<=n;i++)  //n  节点的总数
        if(in[i]==0) q.push(i),dp[i][a[i]-'a']=1;  //将入度为0的点入队列
    
    vector<int>ans;   //ans 为拓扑序列
    while(!q.empty()){
        int p=q.front(); q.pop(); // 选一个入度为0的点,出队列
        ans.push_back(p);
        for(int i=0;i<v[p].size();i++)
        {
            int y=v[p][i];
            for(int j=0;j<26;j++){
                dp[y][j]=max(dp[y][j],dp[p][j]+((a[y]-'a')==j));
                //ma=max(ma,dp[y][j]); 
            }
            in[y]--;
            if(in[y]==0)
                q.push(y); 
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<26;j++){
            ma=max(ma,dp[i][j]);
        }
    }
    cout<<ma<<endl;
}

 

posted @ 2021-04-20 23:58  lipu123  阅读(193)  评论(2编辑  收藏  举报