tarjan缩点+拓扑最长链+类似于SPFA统计方案
代码
//By AcerMo
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=100005;
int n,m,mod,ind,ti;
int in[M],f[M],g[M],jud[M];
int dfn[M],low[M],siz[M],fa[M];
bool vis[M];
stack<int>s;
vector<int>v[M],e[M];
inline int read()
{
int x=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
inline void tarjan(int x)
{
dfn[x]=low[x]=++ind;s.push(x);vis[x]=1;
for (int i=0;i<v[x].size();i++)
{
int go=v[x][i];
if (!dfn[go])
tarjan(go),low[x]=min(low[x],low[go]);
else if (vis[go])low[x]=min(low[x],dfn[go]);
}
if (low[x]==dfn[x])
{
ti++;int u=-1;
while(u!=x)
{
u=s.top();s.pop();
vis[u]=0;fa[u]=ti;
siz[ti]++;
}
}
return ;
}
inline void topsort()
{
queue<int>q;int ans=0,mks=0;
for (int i=1;i<=ti;i++)
{
if(!in[i]) q.push(i);
f[i]=siz[i];g[i]=1;
}
while (q.size())
{
int x=q.front();q.pop();
for (int i=0;i<e[x].size();i++)
{
int go=e[x][i];
in[go]--;
if(!in[go]) q.push(go);
if(jud[go]==x) continue;
if(f[x]+siz[go]>f[go])
f[go]=f[x]+siz[go],g[go]=g[x];
else if(f[x]+siz[go]==f[go])
g[go]=(g[go]+g[x])%mod;
jud[go]=x;
}
}
for (int i=1;i<=ti;i++)
if (f[i]>mks) mks=f[i],ans=g[i];
else if (f[i]==mks) ans=(ans+g[i])%mod;
cout<<mks<<endl<<ans;
return ;
}
int main()
{
n=read();m=read();mod=read();
for (int i=1;i<=m;i++)
{
int x=read(),y=read();v[x].push_back(y);
}
for (int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
for (int x=1;x<=n;x++)
for(int i=0;i<v[x].size();i++)
if(fa[x]!=fa[v[x][i]])
e[fa[x]].push_back(fa[v[x][i]]),in[fa[v[x][i]]]++;
topsort();
return 0;
}