剖析其本质,其实缩点之后的一条链就是一个半联通分量。。那么任务就变成求一个DAG上的最长链及其数量,那么就spfa/拓扑排序/记忆化搜索搞定。。其实是我的OrzCC T3的弱化版233。。
#include<cstdio>
#include<iostream>
#include<memory.h>
#define N 200005
#define clr(a) memset(a,0,sizeof(a))
using namespace std;
struct edge{
int e,next;
}ed[N*10];
int n,m,p,s,e,i,j,ne=0,scc=0,top=0,a[N],t=0,ans=0,sum=0,dp[N],num[N],belong[N],dfn[N],low[N],in[N],st[N],size[N],ins[N];
void add(int s,int e)
{
ed[++ne].e=e;ed[ne].next=a[s];
a[s]=ne;
}
void tarjan(int x)
{
dfn[x]=low[x]=++t;
st[++top]=x;ins[x]=1;
for (int j=a[x];j;j=ed[j].next)
{
if (!dfn[ed[j].e]) tarjan(ed[j].e);
if (ins[ed[j].e]) low[x]=min(low[x],low[ed[j].e]);
}
if (low[x]==dfn[x])
{
++scc;
while (st[top+1]!=x) belong[st[top--]]=n+scc,ins[st[top+1]]=0,size[n+scc]++;
}
}
void dfs(int x,int d)
{
int to;
dfn[x]=d;
dp[x]=size[x];num[x]=1;
for (int j=a[x];j;j=ed[j].next)
if(dfn[to=ed[j].e]<x)
{
dfs(to,d);
if (dp[to]+size[x]>dp[x]) dp[x]=dp[to]+size[x],num[x]=num[to];
else if (dp[to]+size[x]==dp[x]) num[x]=(num[x]+num[to])%p;
}
}
int main()
{
freopen("1093.in","r",stdin);
scanf("%d%d%d",&n,&m,&p);
for(i=1;i<=m;i++)
{
scanf("%d%d",&s,&e);
add(s,e);
}
clr(dfn);clr(low);clr(belong);clr(in);clr(size);clr(ins);
for (i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
for (i=1;i<=n;i++)
for (j=a[i];j;j=ed[j].next)
if (belong[i]!=belong[ed[j].e]) add(belong[i],belong[ed[j].e]),in[belong[ed[j].e]]++;
clr(dp);clr(num);
t=0;
for (i=n+1;i<=n+scc;i++)
if (!in[i])
{
dfs(i,++t);
if (dp[i]>ans) ans=dp[i],sum=num[i];
else if (dp[i]==ans) sum=(sum+num[i])%p;
}
printf("%d\n%d\n",ans,sum);
}
#include<cstdio>
#include<iostream>
#include<memory.h>
#define N 200005
#define clr(a) memset(a,0,sizeof(a))
using namespace std;
struct edge{
int e,next;
}ed[N*10];
int n,m,p,s,e,i,j,ne=0,scc=0,top=0,a[N],t=0,ans=1,sum,dp[N],num[N],belong[N],dfn[N],low[N],in[N],st[N],size[N],ins[N];
void add(int s,int e)
{
ed[++ne].e=e;ed[ne].next=a[s];
a[s]=ne;
}
void tarjan(int x)
{
dfn[x]=low[x]=++t;
st[++top]=x;ins[x]=1;
for (int j=a[x];j;j=ed[j].next)
{
if (!dfn[ed[j].e]) tarjan(ed[j].e);
if (ins[ed[j].e]) low[x]=min(low[x],low[ed[j].e]);
}
if (low[x]==dfn[x])
{
++scc;
while (st[top+1]!=x) belong[st[top--]]=n+scc,ins[st[top+1]]=0,size[n+scc]++;
}
}
void dfs(int x,int d)
{
int to;
dfn[x]=d;
dp[x]=size[x];num[x]=1;
for (int j=a[x];j;j=ed[j].next)
if(dfn[to=ed[j].e]!=x)
{
if (!dfn[to]) dfs(to,x);
dfn[to]=x;
if (dp[to]+size[x]>dp[x]) dp[x]=dp[to]+size[x],num[x]=num[to];
else if (dp[to]+size[x]==dp[x]) num[x]=(num[x]+num[to])%p;
}
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
for(i=1;i<=m;i++)
{
scanf("%d%d",&s,&e);
add(s,e);
}
clr(dfn);clr(low);clr(belong);clr(in);clr(size);clr(ins);
for (i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
for (i=1;i<=n;i++)
for (j=a[i];j;j=ed[j].next)
if (belong[i]!=belong[ed[j].e]) add(belong[i],belong[ed[j].e]),in[belong[ed[j].e]]++;
clr(dp);clr(num);
ans=sum=0;
for (i=n+1;i<=n+scc;i++)
if (!in[i])
{
dfs(i,1);
if (dp[i]>ans) ans=dp[i],sum=num[i];
else if (dp[i]==ans) sum=(sum+num[i])%p;
}
printf("%d\n%d\n",ans,sum);
}