Codeforces Round #460 (Div. 2) D. Substring(拓撲排序)
阿新 • • 發佈:2018-12-24
題意:有一個n個點m條邊的有向圖,每個節點有一個字母,路徑的權值是路徑上相同字母的最大個數。求最大的路徑權值。
思路:因為只有26個字母,所以直接假設其中一個字母為相同字母數最大的字母。列舉每一個字母,通過拓撲排序找到最大權值,取其中的最大值就是答案。當圖中存在環時,答案就是無窮大,輸出-1;
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define PII pair<int,int>
#define PDD pair<double,double>
#define MP(a,b) make_pair(a,b)
#define MOD ((1<<31)-1)
#define INF 0x3f3f3f3f
#define N 100005
int n,m;
char w[300005];
int u,v;
int in[300005],inc[300005];
int num[300005];
vector<int> g[300005];
int TP(char x)
{
memset(num,0,sizeof(num));
int sum=0;
int ans=0;
queue<int> q;
for(int i=1 ;i<=n;i++)
{
inc[i]=in[i];
if(in[i]==0)
{
q.push(i),sum++;
if(w[i]==x) ans=max(ans,num[i]);
}
if(w[i]==x) num[i]++;
}
//cout<<q.size()<<endl;
while(!q.empty())
{
u=q.front();
q.pop();
for (int i=0;i<g[u].size();i++)
{
v=g[u][i];
inc[v]--;
if(inc[v]==0) q.push(v),sum++;
if(w[v]==x) num[v]=max(num[v],num[u]+1);
else num[v]=max(num[v],num[u]);
ans=max(num[v],ans);
}
}
if(sum!=n) return -1;
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m;
cin>>w+1;
memset(in,0,sizeof(in));
for(int i=0;i<m;i++)
{
cin>>u>>v;
g[u].push_back(v);
in[v]++;
}
int ans=0;
for(int i=0;i<26;i++)
{
int tmp=TP((char)('a'+i));
if(tmp==-1)
{
cout<<-1<<endl;
return 0;
}
ans=max(ans,tmp);
}
cout<<ans<<endl;
}