libreoj10092:
题解:缩点之后借用拓扑排序的流程对DAG进行dp(类似于求最短路的方案数)
#include<bits/stdc++.h>
typedef long long LL;
using namespace std;
const int maxn=1e5+10;
int n,m,x;
inline int read()
{
int X=0; bool flag=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
if(flag) return X;
return ~(X-1);
}
vector<int> G[maxn],g[maxn];
int dfn[maxn],low[maxn],cnt;
int bcc[maxn],scc;
stack<int> st;
int ins[maxn];
int sum[maxn];
int in[maxn];
map<pair<int,int>,int> p;
void init()
{
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(ins,0,sizeof(ins));
memset(bcc,0,sizeof(bcc));
memset(sum,0,sizeof(sum));
memset(in,0,sizeof(in));
cnt=0;
scc=0;
for(int i=0;i<=n;i++){
G[i].clear();g[i].clear();
}
while(!st.empty()){
st.pop();
}
}
void tarjan(int u)
{
dfn[u]=low[u]=++cnt;
st.push(u);ins[u]=1;
int len=G[u].size();
for(int i=0;i<len;i++){
int to=G[u][i];
if(!dfn[to]){
tarjan(to);
low[u]=min(low[u],low[to]);
}
else
if(ins[to]){
low[u]=min(low[u],dfn[to]);
}
}
if(dfn[u]==low[u]){
++scc;
int m=0;
while(1){
int pre=st.top();
st.pop();
ins[pre]=0;
m++;
bcc[pre]=scc;
if(pre==u)break;
}
sum[scc]=m;
}
}
queue<int> q;
void build()
{
for(int i=1;i<=n;i++){
for(int j=0;j<G[i].size();j++){
int u=bcc[i],v=bcc[G[i][j]];
pair<int,int> pre=make_pair(u,v);
if(!p[pre]&&u!=v){
g[u].push_back(v);
in[v]++;
p[pre]++;
}
}
}
}
int f[maxn][2],mx;
void dfs()
{
for(int i=1;i<=scc;i++){
if(in[i]==0){
//printf("%d\n",i);
q.push(i);
f[i][0]=1;
f[i][1]=sum[i];
}
}
while(!q.empty()){
int u=q.front();
q.pop();
mx=max(mx,f[u][1]);
for(int i=0;i<g[u].size();i++){
int to=g[u][i];
if(f[u][1]+sum[to]==f[to][1]){
f[to][0]+=f[u][0];
f[to][0]%=x;
}
if(f[u][1]+sum[to]>f[to][1]){
f[to][0]=f[u][0];
f[to][1]=f[u][1]+sum[to];
}
in[to]--;
if(in[to]==0){
q.push(to);
}
}
}
int res=0;
printf("%d\n",mx);
for(int i=1;i<=scc;i++){
if(f[i][1]==mx){
res+=f[i][0];
res%=x;
}
}
printf("%d\n",res);
}
int main()
{
// scanf("%d%d%d",&n,&m,&x);
p.clear();
n=read();m=read();x=read();
init();
int u,v;
for(int i=1;i<=m;i++){
u=read();v=read();
//if(u==v)continue;
//pair<int,int> pre=make_pair(u,v);
G[u].push_back(v);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
tarjan(i);
}
}
build();
dfs();
return 0;
}