- 题目链接
- 大意描述:给定一个n个节点,m条边的有向图,每个节点上有一个小写字母,对于一条路径,它的值为最常出现的字母的数量,求在图中所有路径中,值最大的一条路径的值。但如果值可以任意大,则输出-1.
- 算法:容易得出,如果图中有环,则需要输出-1,否则我们枚举最常出现的字母,然后在图上跑记忆化深搜即可。
-
#include<bits/stdc++.h> #define rep(i,j,k) for(register int i=j;i<=k;i++) using namespace std; template<typename T> void chkmax(T &x,T y){x=max(x,y);} template<typename T> void read(T &num){ char c=getchar();num=0;int f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){num=(num<<3)+(num<<1)+(c^48);c=getchar();} num*=f; } template<typename T> void qwq(T x){ if(x>9)qwq(x/10); putchar(x%10+'0'); } template<typename T> void write(T x){ if(x<0){x=-x;putchar('-');} qwq(x);putchar('\n'); } char st[300010]; struct wzy{ int next,vertice; }edge[300010]; int head[300010];int len=0; inline void add_edge(int x,int y){ edge[++len].next=head[x];edge[len].vertice=y;head[x]=len; return; } bool flag=false;bool vis[300010];bool vis2[300010]; inline void dfs(int x){ if(vis[x])return; if(vis2[x]){flag=true;return;} vis2[x]=true; for(int i=head[x];i;i=edge[i].next){ dfs(edge[i].vertice); } vis2[x]=false; vis[x]=true; return; } int f[300010]; inline int dp(int x,char tmp){ if(f[x]!=-1)return f[x]; int re_value=0; for(int i=head[x];i;i=edge[i].next){ chkmax(re_value,dp(edge[i].vertice,tmp)); } f[x]=re_value+(tmp==st[x-1]); return f[x]; } int main(){ int n,m;read(n);read(m); scanf("%s",st); rep(i,1,m){ int x,y;read(x);read(y); add_edge(x,y); } rep(i,1,n){ dfs(i); if(flag==true)break; } if(flag==true){ write(-1);return 0; } int ans=0; for(char i='a';i<='z';i++){ memset(f,-1,sizeof(f)); rep(j,1,n){ chkmax(ans,dp(j,i)); } } write(ans); return 0; }