无事闲来水一水Tarjan,结果水挂了。。。。。。
先Tarjan缩点。
第一问是DAG上的最长路径(点权)
第二问是最长路径的方案数。
都是DP。
然而第二问坑了。。。。。。
因为没判重边(很明显重新建图的时候会出现重边啊)
毕竟还是弱啊。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int N=100000+5;
const int M=1000000+5;
typedef long long ll;
inline int read(){
int x=0;char ch;
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x;
}
struct Edge{
int to,next;
}e[M],g[M];
int head[N],cnt,last[N];
int val[N],sccno[N],scc_cnt;
int pre[N],lowlink[N],dfs_clock;
int d[N];
ll f[N],mod;
stack<int>s;
int vis[N];
void ins1(int u,int v){
cnt++;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
}
void ins2(int u,int v){
cnt++;g[cnt].to=v;g[cnt].next=last[u];last[u]=cnt;
}
void tarjan(int u){
pre[u]=lowlink[u]=++dfs_clock;
s.push(u);
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(!pre[v]){
tarjan(v);
lowlink[u]=min(lowlink[u],lowlink[v]);
}else if(!sccno[v])lowlink[u]=min(lowlink[u],pre[v]);
}
if(lowlink[u]==pre[u]){
scc_cnt++;
while(true){
int x=s.top();s.pop();
sccno[x]=scc_cnt;
val[scc_cnt]++;
if(x==u)break;
}
}
}
int dp(int u){
if(d[u])return d[u];
d[u]=val[u];
for(int i=last[u];i;i=g[i].next)
d[u]=max(d[u],val[u]+dp(g[i].to));
return d[u];
}
ll calc(int u){
if(f[u])return f[u];
int lim=0;
for(int i=last[u];i;i=g[i].next)
lim=max(lim,d[g[i].to]);
for(int i=last[u];i;i=g[i].next)
if(d[g[i].to]==lim){
if(vis[g[i].to]==u)continue;
vis[g[i].to]=u;
f[u]=(f[u]+calc(g[i].to))%mod;
}
if(!f[u])f[u]=1;
return f[u];
}
int main(){
int n,m;n=read();m=read();mod=read();
int u,v;
while(m--){
u=read();v=read();
ins1(u,v);
}
for(int i=1;i<=n;i++)if(!pre[i])tarjan(i);
cnt=0;
for(int u=1;u<=n;u++)
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(sccno[u]!=sccno[v])
ins2(sccno[u],sccno[v]);
}
int ans=0;
ll num=0;
for(int i=1;i<=scc_cnt;i++)ans=max(ans,dp(i));
printf("%d\n",ans);
for(int i=1;i<=scc_cnt;i++)if(d[i]==ans)num=(num+calc(i))%mod;
printf("%lld",num);
return 0;
}