[ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)
题目链接
Solution
大概是个裸题.
可以考虑到,如果原图是一个有向无环图,那么其最大半联通子图就是最长的一条路.
于是直接 \(Tarjan\) 缩完点之后跑拓扑序 DP就好了.
同时由于是拓扑序DP,要去掉所有的重边.
Code
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=100008;
struct sj{int to,next;}a[maxn*10];
ll mod,dfn[maxn],low[maxn];
ll head[maxn],belong[maxn];
ll du[maxn],w[maxn],v[maxn];
ll tot,sta[maxn],top,size,cnt;
ll num,n,m;
ll f[maxn],js[maxn],ans,ans_siz;
struct kk{int to,fr;}cc[maxn*10];
ll read()
{
char ch=getchar(); ll f=1,w=0;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){w=w*10+ch-'0';ch=getchar();}
return f*w;
}
void add(int x,int y)
{
a[++size].to=y;
a[size].next=head[x];
head[x]=size;
}
void tarjan(int x)
{
dfn[x]=low[x]=++tot;
sta[++top]=x;
v[x]=1;
for(int i=head[x];i;i=a[i].next)
{
int tt=a[i].to;
if(!dfn[tt]){
tarjan(tt);
low[x]=min(low[x],low[tt]);
}
else if(v[tt]) low[x]=min(low[x],dfn[tt]);
}
if(dfn[x]==low[x])
{
belong[x]=++cnt;
v[x]=0;
do{
w[cnt]++;
belong[sta[top]]=cnt;
v[sta[top]]=0;
}while(sta[top--]!=x);
}
}
bool cmp(kk x,kk y)
{
if(x.fr==y.fr)return x.to<y.to;
else return x.fr<y.fr;
}
void work()
{
queue<int>q;
for(int i=1;i<=cnt;i++)
if(!du[i])
q.push(i),v[i]=1,f[i]=w[i],js[i]=1;
while(!q.empty())
{
int x=q.front(); q.pop();
for(int i=head[x];i;i=a[i].next)
{
int tt=a[i].to;
du[tt]--;
if(!du[tt]&&!v[tt])q.push(tt),v[tt]=1;
if(f[tt]==w[tt]+f[x])
js[tt]+=js[x],js[tt]%=mod;
if(f[tt]<w[tt]+f[x])
{
f[tt]=w[tt]+f[x];
js[tt]=js[x]%mod;
}
}
}
}
int main()
{
n=read(); m=read(); mod=read();
for(int i=1;i<=m;i++)
add(read(),read());
for(int i=1;i<=n;i++)
if(!dfn[i])tarjan(i);
for(int x=1;x<=n;x++)
for(int i=head[x];i;i=a[i].next)
{
int tt=a[i].to;
if(belong[tt]!=belong[x])
cc[++num].fr=belong[x],cc[num].to=belong[tt];
}
memset(a,0,sizeof(a));
memset(head,0,sizeof(head));
size=0;
sort(cc+1,cc+num+1,cmp);
for(int i=1;i<=num;i++)
{
if(cc[i].fr==cc[i-1].fr&&cc[i].to==cc[i-1].to)continue;
add(cc[i].fr,cc[i].to),du[cc[i].to]++;
}
work();
for(int i=1;i<=cnt;i++)
if(f[i]>ans)
ans=f[i],ans_siz=js[i];
else if(f[i]==ans)
ans_siz+=js[i],ans_siz%=mod;
cout<<ans<<endl<<(ans_siz+mod)%mod<<endl;
return 0;
}
[ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)的更多相关文章
- [luogu2272 ZJOI2007] 最大半连通子图 (tarjan缩点 拓扑排序 dp)
传送门 题目描述 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向 ...
- 2018.11.06 bzoj1093: [ZJOI2007]最大半连通子图(缩点+拓扑排序)
传送门 先将原图缩点,缩掉之后的点权就是连通块大小. 然后用拓扑排序统计最长链数就行了. 自己yyyyyy了一下一个好一点的统计方法. 把所有缩了之后的点都连向一个虚点. 然后再跑拓扑,这样最后虚点的 ...
- bzoj1093: [ZJOI2007]最大半连通子图 scc缩点+dag上dp
一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V ...
- BZOJ 1093 [ZJOI2007]最大半连通子图 - Tarjan 缩点
Description 定义一个半联通图为 : 对任意的两个点$u, v$,都有存在一条路径从$u$到$v$, 或从$v$到$u$. 给出一个有向图, 要求出节点最多的半联通子图, 并求出方案数. ...
- BZOJ 1093: [ZJOI2007]最大半连通子图( tarjan + dp )
WA了好多次... 先tarjan缩点, 然后题意就是求DAG上的一条最长链. dp(u) = max{dp(v)} + totu, edge(u,v)存在. totu是scc(u)的结点数. 其实就 ...
- Luogu P2272 [ZJOI2007]最大半连通子图(Tarjan+dp)
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的有向路径. ...
- BZOJ1093 ZJOI2007最大半连通子图(缩点+dp)
发现所谓半连通子图就是缩点后的一条链之后就是个模板题了.注意缩点后的重边.写了1h+真是没什么救了. #include<iostream> #include<cstdio> # ...
- BZOJ1093: [ZJOI2007]最大半连通子图(tarjan dp)
题意 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G' ...
随机推荐
- ctrl+shift+f
ctrl+f是在当前文件寻找某个参数 ctrl+shift+f是在整个工程目录下寻找某个参数
- c#中接口、抽象类、继承综合小练习
namespace Test { class Program { static void Main(string[] args) { //作业:橡皮rubber鸭子.木wood鸭子.真实的鸭子real ...
- Bootstrap历练实例:带徽章的列表组
向列表组添加徽章 我们可以向任意的列表项添加徽章组件,它会自动定位到右边.只需要在 <li> 元素中添加 <span class="badge"> 即可.下 ...
- OC和C++的混用1
//Objective-C类 /*在混用之前需要做一步非常重要的事:不是代码而是编译器选项,在做混合编译之前一定要把编译器的Compile Sources As选项改为Objective C++. 修 ...
- ES6 -- 模板字符串(反单引号)
1)直接使用变量 // before var str = 'test'; console.log(str + "123"); // now var str = 'test'; co ...
- [图文]RHEL 7/CentOS 7/Fedora28 联网初始化
实验说明: 入门Linux,一般会遇到以下几个问题: 从哪里获取LInux镜像? 如何通过镜像文件安装Linux系统? 安装实体机还是虚拟机? 安装完系统如何配置网络? 虚拟机的网络配置与实体机有何不 ...
- windows charles 抓包https请求
charles证书 2.设置host和端口 3.浏览器访问即可抓到https的请求
- ccf 201712-3 Crontab(Python实现)
一.原题 问题描述 试题编号: 201712-3 试题名称: Crontab 时间限制: 10.0s 内存限制: 256.0MB 问题描述: 样例输入 3 201711170032 201711222 ...
- paper:synthesizable finit state machine design techniques using the new systemverilog 3.0 enhancements之onehot coding styles(encoded-parameter style with registered outputs不推荐但是经常有人写这样的代码)
这样写法,不利与综合,case语句中比较也是full-vector比较.
- 《Java并发编程实战》读书笔记一 -- 简介
<Java并发编程实战>读书笔记一 -- 简介 并发的历史 并发的历史,也是人类利用有限的资源去提高生产效率的一个的例子. 设想现在有台计算机,这台计算机具有以下的资源: 单核CPU一个 ...