思路
拿到题后首先应该想到缩点(毕竟强连通分量一定是半联通的,这样就生成了一个有向无环图~
在一个有向无环图中的“半联通”就是一条链(因为一条链中的任意两个点都满足定义
那么第一问而言就是找一天最大链,而第二问就是找最大连的条数
注意:重新建边的时候需要去重
Code
#include<bits/stdc++.h>
#define re register
#define ll int long long
using namespace std;
const int N=1e6+10;
int read(){
int sum=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){sum=(sum<<3)+(sum<<1)+(c^48);c=getchar();}
return sum*f;
}
int n,m,mod;
struct node{
int v,nxt;
}e[N];
struct Node{
int u,v;
}c[N],b[N];
bool cmp(Node a,Node b){
return(a.u<b.u||a.u==b.u&&a.v<b.v||a.u==b.u&&a.v==b.v);
}
int u[N],v[N],k,now1,now2;
int dis[N],col,scc[N];
int head[N],cnt,dfn[N],low[N],top,dep,stk[N],color[N],sum[N],rd[N],cd[N];
bool f[N];
void add(int u,int v){
e[++cnt].v=v;
e[cnt].nxt=head[u];
head[u]=cnt;
}
void tarjan(int u){
dfn[u]=low[u]=++dep;
stk[++top]=u;
for(re int i=head[u];i;i=e[i].nxt){
if(!dfn[e[i].v]){
tarjan(e[i].v);
low[u]=min(low[u],low[e[i].v]);
}
else if(!color[e[i].v]){
low[u]=min(low[u],dfn[e[i].v]);
}
}
if(low[u]==dfn[u]){
color[u]=++col;
scc[col]++;
while(stk[top]!=u){
color[stk[top]]=col;
scc[col]++;
top--;
}
top--;
}
}
void dfs(int u,int fa){
f[u]=true;
if(!cd[u]){
dis[u]=scc[u];
sum[u]=1;
return;
}
for(int i=head[u];i;i=e[i].nxt){
if(e[i].v!=fa){
if(!f[e[i].v]) dfs(e[i].v,u);
if(dis[e[i].v]+scc[u]>dis[u]) dis[u]=dis[e[i].v]+scc[u],sum[u]=sum[e[i].v]%mod;
else if(dis[e[i].v]+scc[u]==dis[u]) sum[u]=(sum[u]+sum[e[i].v])%mod;
}
}
}
int main(){
n=read(),m=read(),mod=read();
for(re int i=1;i<=m;i++){
u[i]=read();
v[i]=read();
add(u[i],v[i]);
}
for(re int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i);
}
for(re int i=1;i<=m;i++){
if(color[u[i]]!=color[v[i]]){
k++;
c[k].u=color[u[i]];
c[k].v=color[v[i]];
}
}
sort(c+1,c+1+k,cmp);
cnt=1;
b[cnt].u=c[1].u,b[cnt].v=c[1].v;
now1=b[cnt].u,now2=b[cnt].v;
for(re int i=2;i<=k;i++){
if(c[i].u!=now1||c[i].v!=now2){
cnt++;
b[cnt].u=c[i].u,b[cnt].v=c[i].v;
now1=b[cnt].u,now2=b[cnt].v;
}
}
memset(head,0,sizeof(head));
memset(e,0,sizeof(e));
for(re int i=1;i<=cnt;i++){
cd[b[i].u]++,rd[b[i].v]++;
e[i].nxt=head[b[i].u];
e[i].v=b[i].v;
head[b[i].u]=i;
}
for(re int i=1;i<=col;i++){
if(!rd[i]&&!f[i]) dfs(i,0);
}
int maxn=0,ans=0;
for(re int i=1;i<=col;i++){
if(dis[i]>maxn){
maxn=dis[i];
ans=sum[i];
}
else{
if(maxn==dis[i]){
ans=(ans+sum[i])%mod;
}
}
}
printf("%d\n%d",maxn,ans);
}