题目描述
给一个含n个点m条边的有向无环图(允许重边,点用1到n的整数表示),每条边上有一个字符,问图上有几条路径满足路径上经过的边上的字符组成的的字符串去掉空格后以大写字母开头,句号 '.' 结尾,中间都是小写字母,小写字母可以为0个。
输入描述:
第一行两个整数n,m 接下来m行,每行两个整数a,b和一个字符c,表示一条起点为a,终点为b的边,边上的字符是c 1 ≤ n, m ≤ 50000 1 ≤ a < b ≤ n c可以是大小写字母、句号 '.' 或空格(方便起见用 '_' 表示空格)
输出描述:
输出一个整数,表示答案对232取模的结果
直接拓扑排序+DP嘛
dp[x][0]表示以x节点结尾,路径上只有空格的路径个数
dp[x][1]表示以x节点结尾,路径上去掉空格后,第一个字母是大写字母,大写字母后只有小写字母的路径个数
dp[x][2]表示以x节点结尾,满足题目条件的合法路径个数
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<ctype.h>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define uint unsigned int
#define mod 1000000007
typedef struct
{
int v;
char ch;
}Road;
Road now;
queue<int> q;
vector<Road> G[50005];
int in[50005];
uint dp[50005][3];
int main(void)
{
char ch;
uint ans;
int n, m, i, x, y;
scanf("%d%d", &n, &m);
for(i=1;i<=m;i++)
{
scanf("%d%d %c", &x, &now.v, &now.ch);
G[x].push_back(now);
in[now.v]++;
}
for(i=1;i<=n;i++)
{
if(in[i]==0)
q.push(i);
}
while(q.empty()==0)
{
x = q.front();
q.pop();
for(i=0;i<G[x].size();i++)
{
now = G[x][i];
y = now.v, ch = now.ch;
in[y]--;
if(in[y]==0)
q.push(y);
if(ch=='_')
{
dp[y][0] += dp[x][0]+1;
dp[y][1] += dp[x][1];
dp[y][2] += dp[x][2];
}
else if(isupper(ch))
dp[y][1] += dp[x][0]+1;
else if(islower(ch))
dp[y][1] += dp[x][1];
else
dp[y][2] += dp[x][1];
}
}
ans = 0;
for(i=1;i<=n;i++)
ans += dp[i][2];
printf("%u\n", ans);
return 0;
}