# 2018.8.10T2（缩点，拓扑排序，最长路）

2 3
A B
A C
D D

5

``````#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define ll long long
int n , m;
int id[31][31][31][31] , tot , tt;
int linkk[6100] , t , du[6100];
int dfn[6100] , low[6100] , cnt , cor[6100] , totc;
ll a[6100] , v[6100];
ll dp[6100];
ll jc[30];
struct node{
int n,y,x;
}e[181000];

int read(){int sum = 0;char c = getchar();bool flag = true;while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();if(flag)  return sum;else return -sum;}
ll calc(int A,int B,int C)
{
int D = n - A - B - C;
ll sum = 1;
int a , b , c , d;a = b = c = d = 1;
rep(i,1,n)
{
sum *= i;
for(;a <= A && sum % a == 0;sum/=a,a++);
for(;b <= B && sum % b == 0;sum/=b,b++);
for(;c <= C && sum % c == 0;sum/=c,c++);
for(;d <= D && sum % d == 0;sum/=d,d++);
}
return sum;
}
void pre(){rep(a,0,n) rep(b,0,n-a) rep(c,0,n-a-b) id[a][b][c][n-a-b-c] = ++tot,v[tot] = calc(a,b,c);return;}
char in[40];
void insert(int x,int y)
{
return;
}
void init()
{
rep(x,1,m)
{
int n1,n2,n3,n4;
int m1,m2,m3,m4;
n1 = n2 = n3 = n4 = m1 = m2 = m3 = m4 = 0;
scanf("%s",in+1);
int len = strlen(in+1);
rep(i,1,len)
if(in[i] == 'A') n1++;
else if(in[i] == 'B') n2++;
else if(in[i] == 'C') n3++;
else n4++;
scanf("%s",in+1);
len = strlen(in+1);
rep(i,1,len)
if(in[i] == 'A') m1++;
else if(in[i] == 'B') m2++;
else if(in[i] == 'C') m3++;
else m4++;
m1=n1-m1;m2=n2-m2;m3=n3-m3;m4=n4-m4;
rep(a,n1,n) rep(b,n2,n-a) rep(c,n3,n-a-b)
{
int d = n - a - b - c;
if(d < n4) continue;
insert(id[a][b][c][d],id[a-m1][b-m2][c-m3][d-m4]);
tt++;
}
}
return;
}
stack<int>st;
bool f[6100];
void tarjan(int x)
{
dfn[x] = low[x] = ++cnt;
f[x] = true;st.push(x);
for(int i = linkk[x];i;i = e[i].n)
{
int y = e[i].y;
if(!dfn[y])
{
tarjan(y);
low[x] = min(low[x] , low[y]);
}
else
if(f[y]) low[x] = min(low[x] , dfn[y]);
}
if(low[x] == dfn[x])
{
ll k = v[x];
cor[x] = ++totc;f[x] = false;
while(st.top() != x)
cor[st.top()] = totc,
f[st.top()] = false,k += v[st.top()],
st.pop();
st.pop();a[totc] = k;
}
return;
}
void sd()
{
rep(i,1,tt)
{
int x = e[i].x , y = e[i].y;
if(cor[x] != cor[y])
insert(cor[x] , cor[y]) , du[cor[y]]++;
}
return;
}
queue<int>q;
ll ans = 0;
void topsort()
{
rep(i,1,tot) if(!du[i]) q.push(i);
while(!q.empty())
{
int x = q.front();
dp[x] += a[x];
ans = max(ans,dp[x]);
for(int i = linkk[x];i;i = e[i].n)
{
int y = e[i].y;
du[y]--;
dp[y] = max(dp[y] , dp[x]);
if(!du[y]) q.push(y);
}
q.pop();
}
return;
}
int main()
{