1. 程式人生 > >Codeforces Round #460 (Div. 2) D. Substring(拓撲排序)

Codeforces Round #460 (Div. 2) D. Substring(拓撲排序)

題目連結

題意:有一個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; }