Description
Input
第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述。接下来M行,每行两个正整数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。
Output
应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.
Sample Input
6 6 20070603
1 2
2 1
1 3
2 4
5 6
6 4
1 2
2 1
1 3
2 4
5 6
6 4
Sample Output
3
3
3
HINT
对于100%的数据, N ≤100000, M ≤1000000;对于100%的数据, X ≤10^8。
题解:缩点之后发现最长路就是答案。跑的过程中记录一下方案数。跑最长路的时候需要判重。
具体方法是记录一下每个点上次是由哪个点更新过来的,如果一样就跳过。
一开始数组开小了。。看了两遍竟然没看出来。。。。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 100010
#define M 1000010
int s[N],last[N],cnt,n,m,pre[N],a,b,low[N],point[N],next[M],scc[N],ss,top,size[N];
int point2[N],next2[M],cnt2,temp,d[N],p,l[N*10],h,t,dis[N],sum[N],ans2,ans;
bool f[N];
using namespace std;
struct use{int st,en;}e[M];
struct use2{int st,en;}c[M];
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void add(int x,int y)
{
next[++cnt]=point[x];point[x]=cnt;
e[cnt].st=x;e[cnt].en=y;
}
void add2(int x,int y)
{
d[y]++;
next2[++cnt2]=point2[x];point2[x]=cnt2;
c[cnt2].st=x;c[cnt2].en=y;
}
void dfs(int x)
{
pre[x]=low[x]=++ss;s[++top]=x;
for (int i=point[x];i;i=next[i])
{
int u=e[i].en;
if (!pre[u]){dfs(u);low[x]=min(low[x],low[u]);}
else if (!scc[u]){low[x]=min(low[x],pre[u]);}
}
if (low[x]==pre[x])
{
scc[0]++;
while (top)
{
scc[s[top--]]=scc[0];
size[scc[0]]++;
if (s[top+1]==x) break;
}
}
}
void tarjan()
{
memset(scc,0,sizeof(scc));
for (int i=1;i<=n;i++) if (!pre[i]) dfs(i);
}
void rebuild()
{
for (int i=1;i<=n;i++)
{
for (int j=point[i];j;j=next[j])
if (scc[i]!=scc[e[j].en])
add2(scc[i],scc[e[j].en]);
}
}
void getans()
{
h=0;t=1;
memset(dis,0,sizeof(dis));
for (int i=1;i<=scc[0];i++)if (d[i]==0) {dis[i]=size[i];sum[i]=1;l[++t]=i;}
while (h<t)
{
int u=l[++h];
for (int i=point2[u];i;i=next2[i])
{
d[c[i].en]--;
if (d[c[i].en]==0) l[++t]=c[i].en;
if (u==last[c[i].en]) continue;
last[c[i].en]=u;
if (dis[c[i].en]==dis[u]+size[c[i].en])
(sum[c[i].en]+=sum[u])%=p;
if (dis[c[i].en]<dis[u]+size[c[i].en])
{
dis[c[i].en]=dis[u]+size[c[i].en];
sum[c[i].en]=sum[u];
}
}
}
}
int main()
{
n=read();m=read();p=read();
for (int i=1;i<=m;i++)
{
a=read();b=read();
add(a,b);
}
tarjan();
rebuild();
getans();
for (int i=1;i<=scc[0];i++) ans=max(ans,dis[i]);
for (int i=1;i<=scc[0];i++) if (ans==dis[i]) (ans2+=sum[i])%=p;
cout<<ans<<endl<<ans2<<endl;
}