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