思路:$tarjan+DP$

提交:1次

题解:首先对于一个强连通分量一定是一个半连通分量,并且形成的半连通分量的大小一定是它的$size$,所以我们先缩点。

这样,我们相当于要在新的$DAG$上找一个最长链(一旦有分叉边就不可能是一个半连通分量)。

于是乎写了个$dfs$,$sz[u]$表示这个(缩完后的)点的包含点的数量,$mx[u]$表示以$u$为起点最长链的长度,$tot[u]$表示方案数。

但是注意这个图有可能不连通。

#include<cstdio>
#include<iostream>
#include<map>
#define ull unsigned long long
#define ll long long
#define R register int
using namespace std;
#define pause (for(R i=1;i<=10000000000;++i))
#define In freopen("NOIPAK++.in","r",stdin)
#define Out freopen("out.out","w",stdout)
namespace Fread {
static char B[<<],*S=B,*D=B;
#ifndef JACK
#define getchar() (S==D&&(D=(S=B)+fread(B,1,1<<15,stdin),S==D)?EOF:*S++)
#endif
inline int g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
if(ch==EOF) return EOF; do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
} inline bool isempty(const char& ch) {return (ch<=||ch>=);}
inline void gs(char* s) {
register char ch; while(isempty(ch=getchar()));
do *s++=ch; while(!isempty(ch=getchar()));
}
} using Fread::g; using Fread::gs;
namespace Luitaryi {
const int N=,M=;
map<pair<int,int>,bool> mp;
int n,m,mod;
int vr[M<<],nxt[M<<],fir[M<<],cnt;
inline void add(int u,int v) {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
int vv[M<<],nn[M<<],ff[M<<],ct;
inline void adde(int u,int v) {vv[++ct]=v,nn[ct]=ff[u],ff[u]=ct;}
int dfn[N],low[N],c[N],stk[N],sz[N],t[N],num,cc,top;
bool vis[N];
inline void tarjan(int u) {
dfn[u]=low[u]=++num; stk[++top]=u,vis[u]=true;
for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
if(!dfn[v]) {
tarjan(v);
low[u]=min(low[u],low[v]);
} else if(vis[v]) low[u]=min(low[u],dfn[v]);
} if(dfn[u]==low[u]) {
++cc; R tmp;
do tmp=stk[top],--top,c[tmp]=cc,++sz[cc],vis[tmp]=false; while(tmp!=u);
}
}
int anss,ans,mx[N],tot[N];
inline void dfs(int u) {
vis[u]=true; mx[u]=sz[u],tot[u]=;
for(R i=ff[u];i;i=nn[i]) { R v=vv[i];
if(!vis[v]) dfs(v);
if(sz[u]+mx[v]>mx[u]) {
mx[u]=sz[u]+mx[v];
tot[u]=tot[v];
} else if(sz[u]+mx[v]==mx[u])
tot[u]=(tot[u]+tot[v])%mod;
} ans=max(mx[u],ans);
}
inline void main() {
n=g(),m=g(),mod=g();
for(R i=,u,v;i<=m;++i) u=g(),v=g(),add(u,v);
for(R i=;i<=n;++i) if(!dfn[i]) tarjan(i);
for(R u=;u<=n;++u) for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
if(c[u]!=c[v]&&mp.find(make_pair(c[u],c[v]))==mp.end())
++t[c[v]],adde(c[u],c[v]),mp[make_pair(c[u],c[v])]=true;
} for(R i=;i<=cc;++i) if(!t[i]||!vis[i]) dfs(i);
for(R i=;i<=cc;++i) if(mx[i]==ans) anss=(anss+tot[i])%mod;
printf("%d\n%d\n",ans,anss);
}
}
signed main() {
Luitaryi::main();
return ;
}

2019.07.22

最新文章

  1. JS中class和id的区别
  2. easyconf——基于AugularJS的配置管理系统开发框架
  3. OC使用inline替代宏
  4. iOS视频录制、压缩导出、取帧
  5. Where Jboss7.1 take war application to deploy--reference
  6. poj1915 BFS
  7. 首次启动优美新手指引tip
  8. 文档在线预览开源实现方案一:OpenOffice + SwfTools + FlexPaper
  9. Linux内核打印时间戳
  10. angular2 学习笔记 ( 第3方插件 jQuery and ckeditor )
  11. win10安装tensorflow-gpu1.13.1+cuda10.0+cudnn7.3.1
  12. CADisplayLink以及定时器的使用
  13. 并发之java.util.concurrent.atomic原子操作类包
  14. 通信原理之UDP协议(四)
  15. 【转】每天一个linux命令(47):iostat命令
  16. 如何快速地编写和运行一个属于自己的 MapReduce 例子程序
  17. NOIP2015&amp;2016普及组解题报告
  18. JAVA 9 新特性
  19. hadoop 3.1.1 安装
  20. 类中的迭代器__iter__

热门文章

  1. ubuntu内lnmp相关操作命令
  2. Python列表推导
  3. Nginx关联php安装及启动
  4. EXIT(外部中断)控制实验
  5. 22-MySQL DBA笔记-其他产品的选择
  6. (七)lucene之中文检索和高亮显示以及摘要
  7. winform c# 请求网站,返回Json字符串
  8. ASP.NET Core 入门(4)(IIS 部署前后端站点)
  9. .net Core如何对静态文件的访问进行鉴权操作?
  10. Idea查看一个类和子类(实现类)的结构图