题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1093

先缩点,然后就是找最长链,DP一下即可;

注意缩点后的重边!会导致重复计算答案。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const maxn=1e5+,maxm=1e6+;
int n,m,mod,hd[maxn],ct,col[maxn],cr,tim,dfn[maxn],low[maxn],sta[maxn],top,h,t;
int f[maxn],s[maxn],siz[maxn],deg[maxn],ans,mk[maxn];
ll cnt;
bool vis[maxn];
struct N{
int fr,to,nxt;
N(int f=,int t=,int n=):fr(f),to(t),nxt(n) {}
}ed[maxm];
void add(int x,int y){ed[++ct]=N(x,y,hd[x]); hd[x]=ct;}
//void add2(int x,int y){edge[++xt]=N(y,head[x]); head[x]=xt;}
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-; ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return ret*f;
}
void tarjan(int x)
{
dfn[x]=low[x]=++tim;
sta[++top]=x; vis[x]=;
for(int i=hd[x],u;i;i=ed[i].nxt)
{
if(!dfn[u=ed[i].to])tarjan(u),low[x]=min(low[x],low[u]);
else if(vis[u])low[x]=min(low[x],dfn[u]);
}
if(low[x]==dfn[x])
{
cr++; int y;
while((y=sta[top])!=x)col[y]=cr,vis[y]=,siz[cr]++,top--;
col[x]=cr; vis[x]=; siz[cr]++; top--;
}
}
void topo()
{
// for(int i=1;i<=cr;i++)
// if(!deg[i])q.push(i),f[i]=siz[i],s[i]=1;
h=; t=;
for(int i=;i<=cr;i++)
if(!deg[i])sta[++t]=i,f[i]=siz[i],s[i]=;
while(h<=t)
{
// int x=q.front(); q.pop();
int x=sta[h]; h++;
for(int i=hd[x],u;i;i=ed[i].nxt)
{
deg[u=ed[i].to]--; if(!deg[u])sta[++t]=u;//
if(mk[u]==x)continue;//注意处理连通块之间的重边!
if(f[u]<f[x]+siz[u])f[u]=f[x]+siz[u],s[u]=s[x];
else if(f[u]==f[x]+siz[u])s[u]=(s[u]+s[x])%mod;
mk[u]=x;
}
}
}
int main()
{
n=rd(); m=rd(); mod=rd();
for(int i=,x,y;i<=m;i++)
{
x=rd(); y=rd();
add(x,y);
}
for(int i=;i<=n;i++)
if(!dfn[i])tarjan(i);
ct=; memset(hd,,sizeof hd);
for(int i=;i<=m;i++)
{
int u=ed[i].fr,v=ed[i].to;
if(col[u]==col[v])continue;
add(col[u],col[v]); deg[col[v]]++;
}
// for(int i=1;i<=n;i++)
// for(int j=hd[i],u;j;j=ed[j].nxt)
// {
// if(col[i]==col[u=ed[j].to])continue;
// add2(col[i],col[u]); deg[col[u]]++;
// }
topo();
for(int i=;i<=cr;i++)
{
if(f[i]>ans)ans=f[i],cnt=s[i];
else if(f[i]==ans)(cnt+=s[i])%=mod;
}
printf("%d\n%lld\n",ans,cnt);
return ;
}

bzoj 1093 [ ZJOI 2007 ] 最大半连通子图 —— 拓扑+DP的更多相关文章

  1. BZOJ 1093: [ZJOI2007]最大半连通子图( tarjan + dp )

    WA了好多次... 先tarjan缩点, 然后题意就是求DAG上的一条最长链. dp(u) = max{dp(v)} + totu, edge(u,v)存在. totu是scc(u)的结点数. 其实就 ...

  2. BZOJ1093: [ZJOI2007]最大半连通子图(tarjan dp)

    题意 一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G' ...

  3. Luogu P2272 [ZJOI2007]最大半连通子图(Tarjan+dp)

    P2272 [ZJOI2007]最大半连通子图 题意 题目描述 一个有向图\(G=(V,E)\)称为半连通的\((Semi-Connected)\),如果满足:\(\forall u,v\in V\) ...

  4. P2272 [ZJOI2007]最大半连通子图 tarjan+DP

    思路:$tarjan+DP$ 提交:1次 题解:首先对于一个强连通分量一定是一个半连通分量,并且形成的半连通分量的大小一定是它的$size$,所以我们先缩点. 这样,我们相当于要在新的$DAG$上找一 ...

  5. BZOJ 1093 [ZJOI2007] 最大半连通子图(强联通缩点+DP)

    题目大意 题目是图片形式的,就简要说下题意算了 一个有向图 G=(V, E) 称为半连通的(Semi-Connected),如果满足图中任意两点 u v,存在一条从 u 到 v 的路径或者从 v 到 ...

  6. bzoj 1093 最大半连通子图 - Tarjan - 拓扑排序 - 动态规划

    一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径.若G'=(V ...

  7. BZOJ 1093 [ZJOI2007]最大半连通子图

    1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 1986  Solved: 802[Submit][St ...

  8. bzoj 1093 [ZJOI2007]最大半连通子图(scc+DP)

    1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 2286  Solved: 897[Submit][St ...

  9. BZOJ 1093 最大半连通子图 题解

    1093: [ZJOI2007]最大半连通子图 Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 2767  Solved: 1095[Submit][S ...

随机推荐

  1. java攻城狮之路--复习JDBC

    1.JDBC中如何获取数据库链接Connection? Driver 是一个接口: 数据库厂商必须提供实现的接口. 能从其中获取数据库连接. 可以通过 Driver 的实现类对象获取数据库连接. 1. ...

  2. Java_Web三大框架之Hibernate 入门(一)

    一.Hibernate简介: Hibernate作者——Gavin King Hibernate创始人 < Hibernate in action >作者 EJB 3.0的Entity b ...

  3. python 将中文转拼音后填充到url做参数并写入excel

    闲着没事写了个小工具,将中文转拼音后填充到url做参数并写如excel 一.先看下演示,是个什么东西 二.代码 代码用到一个中文转拼音的库,库是网上下的,稍微做了下修改,已经找不原来下载的地址了,然后 ...

  4. Photoshop如何实现图片相对画布居中

    先按ctrl+A,再选择要居中的图层,然后就会发现居中按钮被激活了

  5. .net 学习视频

    http://www.iqiyi.com/a_19rrh9jx9p.html http://www.cnblogs.com/aarond/p/SQLDispatcher.html  --读写分离 ht ...

  6. (C/C++学习)12.获取系统时间制作时钟(system()略解)

    说明:通过调用函数来获取系统当前时间,并制作一个数字式的时钟,时钟的显示包括年.月.日.小时.分以及秒,通过系统屏幕的刷新来对不断更新的时间进行屏幕的显示. 一.对相关函数的学习 1.time_t t ...

  7. Linux:在安装虚拟机时如何选择网络类型?

    如图所示工作站提供了5种网络模式,我们主要用的就是上面3种:桥接模式,NAT,仅主机 1,仅主机模式 仅主机模式:虚拟机用过vmnet1网卡与宿主机通信,但是不能与物理局域网内其他主机通信,可利用虚拟 ...

  8. MySQL之中文乱码问题

    创建 my.ini 文件,在该文件中添加以下内容,放在安装好的mysql根路径下: [client] default-character-set=utf8 [mysql] # 设置mysql客户端默认 ...

  9. 爬虫系列(九) xpath的基本使用

    一.xpath 简介 究竟什么是 xpath 呢?简单来说,xpath 就是一种在 XML 文档中查找信息的语言 而 XML 文档就是由一系列节点构成的树,例如,下面是一份简单的 XML 文档: &l ...

  10. 【Codeforces 478C】Table Decorations

    [链接] 我是链接,点我呀:) [题意] 给你r,g,b三种颜色的气球 每张桌子要放3个气球 但是3个气球的颜色不能全都一样 (允许两个一样,或者全都不一样) 问你最多能装饰多少张桌子 [题解] 先把 ...