1. 程式人生 > >codeforces 919D 記憶化+判環

codeforces 919D 記憶化+判環

題意:在有向圖中找出一條路徑上邊出現的相同顏色最多的,輸出這個相同顏色,有環輸出-1.
思路:對於每一個點進行記憶化搜尋,這裡的vis陣列的妙用,vis == -1表示未訪問過,vis == 0表示已經訪問過,vis == 1表示這個節點所有子樹已經訪問過,所以可以返回值。判斷環的話出現了vis == 0那麼表示有環。

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;
#define clr(x,y) memset(x,y,sizeof x)
typedef long long ll; const int maxn = 3e5 + 10; #define INF 0x3f3f3f3f const ll Mod = 1e9 + 7; struct Edge{int to,next;}edge[maxn << 1]; int head[maxn],vis[maxn],edge_num;//vis == -1表示未訪問過,vis == 0表示這個點已經被訪問了,vis == 1表示這個點的所有子節點全部被訪問了 int dp[maxn][26]; char s[maxn]; void Init() { edge_num = 0
;clr(head,-1);clr(dp,0);clr(vis,-1); } void add_edge(int x,int y) { edge[edge_num] = (Edge){y,head[x]};head[x] = edge_num ++; } bool dfs(int u) { if(vis[u] == 0)return false; if(vis[u] == 1)return true; vis[u] = 0; for(int i = head[u];i != -1;i = edge[i].next) { int v = edge[i].to; // cout << u << " -> " << v << endl;
if(!dfs(v))return false; for(int j = 0;j < 26;j ++) { dp[u][j] = max(dp[u][j],dp[v][j]); } } vis[u] = 1;dp[u][s[u] - 'a'] ++; return true; } int n,m; int solve() { for(int i = 1;i <= n;i ++) { if(vis[i] == -1) { if(!dfs(i))return -1; } } int ans = 0; for(int i = 1;i <= n;i ++) for(int j = 0;j < 26;j ++) ans = max(ans,dp[i][j]); return ans; } int main() { while( ~ scanf("%d%d",&n,&m)) { Init();scanf("%s",s + 1); for(int i = 1;i <= m;i ++) { int x,y;scanf("%d%d",&x,&y); add_edge(x,y); } int ans = solve(); printf("%d\n",ans); } return 0; }