P2272 [ZJOI2007]最大半连通子图 tarjan+DP
思路:$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
P2272 [ZJOI2007]最大半连通子图 tarjan+DP的更多相关文章
- Luogu P2272 [ZJOI2007]最大半连通子图(Tarjan+dp)
P2272 [ZJOI2007]最大半连通子图 题意 题目描述 一个有向图\(G=(V,E)\)称为半连通的\((Semi-Connected)\),如果满足:\(\forall u,v\in V\) ...
- BZOJ 1093: [ZJOI2007]最大半连通子图( tarjan + dp )
WA了好多次... 先tarjan缩点, 然后题意就是求DAG上的一条最长链. dp(u) = max{dp(v)} + totu, edge(u,v)存在. totu是scc(u)的结点数. 其实就 ...
- BZOJ1093: [ZJOI2007]最大半连通子图(tarjan dp)
题意 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G' ...
- 洛谷 P2272 [ZJOI2007]最大半连通子图 解题报告
P2272 [ZJOI2007]最大半连通子图 题目描述 一个有向图\(G=(V,E)\)称为半连通的\((Semi-Connected)\),如果满足:\(\forall u,v \in V\),满 ...
- 【bzoj1093】[ZJOI2007]最大半连通子图 Tarjan+拓扑排序+dp
题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:对于u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径. ...
- [luogu2272 ZJOI2007] 最大半连通子图 (tarjan缩点 拓扑排序 dp)
传送门 题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向 ...
- luogu P2272 [ZJOI2007]最大半连通子图
题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若 ...
- [ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)
题目链接 Solution 大概是个裸题. 可以考虑到,如果原图是一个有向无环图,那么其最大半联通子图就是最长的一条路. 于是直接 \(Tarjan\) 缩完点之后跑拓扑序 DP就好了. 同时由于是拓 ...
- BZOJ 1093 [ZJOI2007]最大半连通子图 - Tarjan 缩点
Description 定义一个半联通图为 : 对任意的两个点$u, v$,都有存在一条路径从$u$到$v$, 或从$v$到$u$. 给出一个有向图, 要求出节点最多的半联通子图, 并求出方案数. ...
随机推荐
- PHP中类成员的访问控制
类成员访问控制: 1.public 默认的,任何地方都可以访问,类内,类外,子类中 2.protected 受保护的,对外是封闭的,但是类内部和子类可以访问 3.private 私有的,仅限于本类中 ...
- oddo
看了这张图,或许你对odoo有了一些兴趣. https://www.cnblogs.com/wterp/p/9093616.html 这次就是和大家一起交流开源ERP/CRM系统:odoo 对以下读者 ...
- 复杂链表的复制——牛客offer
题目描述: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head.(注意,输出结果中请不要返回参数中的节点引用, ...
- What's new in C# 7.0
1.数字分隔符(Digit Separators ) 数字分隔符使代码更具可读性.在声明变量时,可以将_添加到单独的数字中.编译器只删除_.以下代码片段在C#7中看起来更具可读性: In C# 6 l ...
- Ctrl+R快速启动应用程序
1.打开注册表 Ctrl+R搜索框中键入“regedit”,回车打开注册表 2.找到HKEY_LOCAL_MACHINE中的如下路径 HKEY_LOCAL_MACHINE\SOFTWARE\Micro ...
- Css制作table细线表格
制作细线表格,我想应该是最基本的css知识了,记录下来巩固下. 推荐: table{ border-collapse:collapse; border: 1px solid #000000; } td ...
- nodejs入门API之net模块
net常用API解析以及应用 手动解析HTTP请求头 基于网络模块net与文件模块fs搭建简易的node服务 net模块部分API参数详细解析 一.net常用API解析以及简单的应用 net模块的组成 ...
- layer弹出层移动端组件
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name ...
- 【OGG 故障处理】OGG-01028
通过ATSCN 的方式启动REPLICAT 进程的时候报错 GGSCI> START REPLICAT RP_XXXX1, ATCSN 15572172378 GGSCI> VIEW RE ...
- RT-Thread--时间管理
时钟节拍 时钟节拍是特定的周期中断,可以看是系统心跳,中断之间的时间间隔取决于不同的应用,一般是 1ms–100ms,时钟节拍率越快,系统的额外开销就越大,从系统启动开始计数的时钟节拍数称为系统时间. ...