首先可以用tarjan进行缩点,因为缩点后的结果对答案不会造成影响
然后就可以按照拓扑序进行求解了
方案数可以用dp的方式去求
注意:要在缩完点之后进行去重的操作,否则方案数会被算大
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
const int maxm=1e6+5;
int n,m,times,tot,head[maxn],dfn[maxn],low[maxn];
long long mod,in[maxn];
struct edge
{
int to,nxt;
}e[maxm<<1];
void add(int x,int y)
{
e[++tot].nxt=head[x];
e[tot].to=y;
head[x]=tot;
}
int col_num,top,inin[maxn],col[maxn],a[maxm],b[maxm],sta[maxn],sz[maxn];
/*
void tarjan(int x)
{
low[x]=dfn[x]=++times;
sta[++top]=x;
for(int i=head[x];i;i=e[i].nxt)
{
int to=e[i].to;
if(!dfn[to])
{
tarjan(to);
low[x]=min(low[x],low[to]);
}
else if(!col[to])
{
low[x]=min(low[x],dfn[to]);
}
}
if(dfn[x]==low[x])
{
col[x]=++col_num;
++sz[col_num];
while(sta[top]!=x)
{
++sz[col_num];
col[sta[top]]=col_num;
top--;
}
top--;
}
}*/
void tarjan(int x){
dfn[x] = low[x] = ++ times;
sta[ ++ top] = x;
inin[x] = true;
for(int i = head[x];i;i = e[i].nxt){
int y = e[i].to;
if(!dfn[y]){
tarjan(y);
low[x] = min(low[x],low[y]);
}
else if(inin[y]){
low[x] = min(low[x], dfn[y]);
}
}
if(dfn[x] == low[x]){
int y;
++col_num;
do{
y = sta[top -- ];
inin[y] = false;
col[y] = col_num;
sz[col_num] ++ ;
}while(x != y);
}
}
int cnt[maxm];
bool cmp(int x,int y)
{
if(a[x]!=a[y]) return a[x]<b[y];
return b[x]<b[y];
}
void build()
{
memset(head,0,sizeof(head)); tot=0;
map <long long,int> st;
for(int i=1;i<=m;i++)
{
a[i]=col[a[i]]; b[i]=col[b[i]];
long long has=a[i]*100000ll+b[i];
if((a[i]!=b[i]) && !st[has])
{
++inin[b[i]];
add(a[i],b[i]);
st[has]=1;
}
}
}
long long ans,dis[maxn];
void toposort()
{
memset(in,0,sizeof(in));
for(int i = col_num;i >= 1;-- i){
if(!dis[i]){
dis[i] = sz[i];
in[i] = 1;
}
for(int j = head[i];j;j = e[j].nxt){
int k = e[j].to;
if(dis[k] < dis[i] + sz[k]){
dis[k] = dis[i] + sz[k];
in[k] = in[i];
}
else if(dis[k] == dis[i] + sz[k]){
in[k] = (in[k] + in[i]) % mod;
}
}
}
long long maxx = 0,sum = 0;
for(int i = 1;i <= n;++i){
if(dis[i] > maxx){
maxx = dis[i];
sum = in[i];
}
else if(dis[i] == maxx){
sum = (sum + in[i] ) % mod;
}
}
printf("%lld\n%lld\n",maxx, sum);
}
long long anss;
void calc()
{
for(int i=1;i<=n;i++)
{
if(dis[i]==dis[ans])
anss=(anss+in[i])%mod;
}
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d%d%lld",&n,&m,&mod);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a[i],&b[i]);
add(a[i],b[i]);
}
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
build();
toposort();
// calc();
// printf("%lld\n%lld",dis[ans],anss);
return 0;
}