#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<stack>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
#define qwq(x) for(edge *o=head[x];o;o=o->next)
#define qaq(x) for(edge *o=h[x];o;o=o->next)
int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)) {
if(c==‘-‘) f=-1;c=getchar();
}
while(isdigit(c)) x=x*10+c-‘0‘,c=getchar();
return x*f;
}
const int nmax=1e5+5;
const int maxn=1e6+5;
const int inf=0x7f7f7f7f;
struct edge{
int to;edge *next;
};
edge es[maxn<<1],*pt=es,*head[nmax];
void add(int u,int v){
pt->to=v;pt->next=head[u];head[u]=pt++;
}
int pre[nmax],scc[nmax],size[nmax],dfs_clock,scc_cnt,mod;
stack<int>s;
void mins(int &a,int b){
if(a>b) a=b;
}
void maxs(int &a,int b){
if(a<b) a=b;
}
int dfs(int x){
int lowu=pre[x]=++dfs_clock;s.push(x);
qwq(x) {
if(!pre[o->to]) mins(lowu,dfs(o->to));
else if(!scc[o->to]) mins(lowu,pre[o->to]);
}
if(lowu==pre[x]){
scc_cnt++;int o,cnt=0;
while(1){
o=s.top();s.pop();
scc[o]=scc_cnt;cnt++;
if(o==x) break;
}
size[scc_cnt]=cnt;
}
return lowu;
}
edge *h[nmax];
bool vis[nmax];int son[nmax],sum[nmax],orz[nmax];
void adde(int u,int v){
pt->to=v;pt->next=h[u];h[u]=pt++;
}
void Dfs(int x){
vis[x]=1;int cnt=0;
qaq(x) {
if(!vis[o->to]) Dfs(o->to);maxs(cnt,son[o->to]);
}
son[x]=cnt+size[x];
}
void DFS(int x){
vis[x]=1;
qaq(x){
if(!vis[o->to]) DFS(o->to);
if(son[x]==son[o->to]+size[x]&&orz[o->to]!=x) sum[x]=(sum[x]+sum[o->to])%mod,orz[o->to]=x;
}
if(!h[x]) sum[x]=1;
}
int main(){
int n=read(),m=read(),u,v;mod=read();
rep(i,1,m) u=read(),v=read(),add(u,v);
rep(i,1,n) if(!pre[i]) dfs(i);
//rep(i,1,n) printf("%d ",scc[i]);printf("\n");
rep(i,1,n) {
u=scc[i];
qwq(i) if(u!=scc[o->to]) adde(u,scc[o->to]);
}
int ans=0;
rep(i,1,scc_cnt) if(!vis[i]) Dfs(i),maxs(ans,son[i]);
//rep(i,1,scc_cnt) printf("%d ",son[i]);printf("\n");
int res=0;clr(vis,0);
rep(i,1,scc_cnt) if(!vis[i]) {
if(son[i]==ans) DFS(i),res=(res+sum[i])%mod;
}
printf("%d\n%d\n",ans,res);
return 0;
}
一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意
两点u,v,存在一条u到v的有向路径或者从v到u的有向路径。若G‘=(V‘,E‘)满足V‘?V,E‘是E中所有跟V‘有关的边,
则称G‘是G的一个导出子图。若G‘是G的导出子图,且G‘半连通,则称G‘为G的半连通子图。若G‘是G所有半连通子图
中包含节点数最多的,则称G‘是G的最大半连通子图。给定一个有向图G,请求出G的最大半连通子图拥有的节点数K
,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出C对X的余数。
第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述接下来M行,每行两个正整
数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。N ≤1
00000, M ≤1000000;对于100%的数据, X ≤10^8
应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.