问题描述

LG2272

BZOJ1093


题解

观察半联通的定义,发现图中的一些结点,构成的链一定是一个半联通子图。

此时存在的环可能会干扰求解,于是\(\mathrm{Tarjan}\)缩点。

于是求最长链,过程中计数即可。


\(\mathrm{Code}\)

#include<bits/stdc++.h>
using namespace std; template <typename Tp>
void read(Tp &x){
x=0;char ch=1;int fh;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-'){
fh=-1;ch=getchar();
}
else fh=1;
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
x*=fh;
} const int maxn=100000+7;
const int maxm=1000000+7;
int n,m,mod; int Head_old[maxn],Next_old[maxm],to_old[maxm],tot_old,u_old[maxm];
int Head_new[maxn],Next_new[maxm],to_new[maxm],tot_new,u_new[maxm]; int size[maxn]; void add_old(int x,int y){
to_old[++tot_old]=y,Next_old[tot_old]=Head_old[x],Head_old[x]=tot_old,u_old[tot_old]=x;
} void add_new(int x,int y){
to_new[++tot_new]=y,Next_new[tot_new]=Head_new[x],Head_new[x]=tot_new,u_new[tot_new]=x;
} int dfn[maxn],low[maxn],cnt,sta[maxn],ind,top;
bool ins[maxn]; int bel[maxn],rd[maxn],cd[maxn]; void tarjan(int x){//错误笔记:Tarjan没写instack
low[x]=dfn[x]=++ind;sta[++top]=x;ins[x]=1;
for(int i=Head_old[x];i;i=Next_old[i]){
int y=to_old[i];
if(dfn[y]){ if(ins[y]) low[x]=min(low[x],dfn[y]);}
else{
tarjan(y);low[x]=min(low[x],low[y]);
}
}
if(dfn[x]==low[x]){
++cnt;
while(sta[top]!=x){
bel[sta[top]]=cnt,ins[sta[top]]=0,top--;size[cnt]++;
}
bel[sta[top]]=cnt,top--;size[cnt]++;ins[x]=0;
}
} set < pair<int,int> > st; int que[maxn],rear,fro=1,copyright;
int lft; bool str[maxn]; void toposort(){
lft=n;
for(int i=1;i<=cnt;i++){
if(!rd[i]) que[++rear]=i,--lft,str[i]=1;
}
while(fro<=rear){
int x=que[fro];++fro;
for(int i=Head_new[x];i;i=Next_new[i]){
int y=to_new[i];--rd[y];
if(!rd[y]) que[++rear]=y,--lft;
}
}
} int cot,length; bool vis[maxn];
int dep[maxn];
int sum[maxn]; void dfs(int x,int fa){
if(vis[x]) return;
vis[x]=1;
if(!cd[x]){
dep[x]=size[x];sum[x]=1;return;
}
for(int i=Head_new[x];i;i=Next_new[i]){
int y=to_new[i];
if(y==fa) continue;
dfs(y,x);
if(dep[y]+size[x]>dep[x]) dep[x]=dep[y]+size[x],sum[x]=sum[y]%mod;
else if(dep[y]+size[x]==dep[x]) sum[x]=(sum[x]+sum[y])%mod;
}
} void calc(){
for(int i=1;i<=cnt;i++){
if(dep[i]>length){
length=dep[i];cot=sum[i];
}
else if(dep[i]==length){
cot=(cot+sum[i])%mod;
}
}
} void debug_rebuild(){
puts("function debug_rebuild");
printf("Node number : %d\n",cnt);
printf("Edge number : %d\n",tot_new);
for(int i=1;i<=tot_new;i++){
printf("Edge %d u:%d v:%d\n",i,u_new[i],to_new[i]);
}
puts("\nbelong:");
for(register int i=1;i<=n;i++){
printf("Node %d belong to %d\n",i,bel[i]);
}
} int main(){
read(n);read(m);read(mod);
for(int xx,yy,i=1;i<=m;i++){
read(xx);read(yy);add_old(xx,yy);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=tot_old;i++){
int x=bel[u_old[i]],y=bel[to_old[i]];
if(x==y) continue;
if(st.count(make_pair(x,y))==1) continue;
st.insert(make_pair(x,y));add_new(x,y);
++rd[y];++cd[x];
}
//debug!
/* puts("");
puts("********************************************************");
puts("");
debug_rebuild();
puts("");
puts("********************************************************");
puts("");*/
//end debug toposort();
for(int i=1;i<=cnt;i++){
if(!vis[i]&&str[i]) dfs(i,0);
}
calc();
printf("%d\n%d\n",length,cot);
return 0;
}

LG2272/BZOJ1093 「ZJOI2007」最大半连通子图 Tarjan缩点+DAG求最长链的更多相关文章

  1. 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 ...

  2. [luogu2272 ZJOI2007] 最大半连通子图 (tarjan缩点 拓扑排序 dp)

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

  3. [ZJOI2007]最大半连通子图 (Tarjan缩点,拓扑排序,DP)

    题目链接 Solution 大概是个裸题. 可以考虑到,如果原图是一个有向无环图,那么其最大半联通子图就是最长的一条路. 于是直接 \(Tarjan\) 缩完点之后跑拓扑序 DP就好了. 同时由于是拓 ...

  4. BZOJ 1093 [ZJOI2007]最大半连通子图 - Tarjan 缩点

    Description 定义一个半联通图为 : 对任意的两个点$u, v$,都有存在一条路径从$u$到$v$, 或从$v$到$u$. 给出一个有向图, 要求出节点最多的半联通子图,  并求出方案数. ...

  5. BZOJ1093 ZJOI2007最大半连通子图(缩点+dp)

    发现所谓半连通子图就是缩点后的一条链之后就是个模板题了.注意缩点后的重边.写了1h+真是没什么救了. #include<iostream> #include<cstdio> # ...

  6. 【bzoj1093】[ZJOI2007]最大半连通子图 Tarjan+拓扑排序+dp

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

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

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

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

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

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

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

随机推荐

  1. springboot+shrio简易登录登出和用户权限认证。

    源码:https://github.com/huangshengz/myJavaDemo本例子参考:https://www.cnblogs.com/HowieYuan/p/9259638.html 本 ...

  2. MySQL统计信息简介

    作者:王小龙@网易乐得DBA 原文地址: http://mp.weixin.qq.com/s/698g5lm9CWqbU0B_p0nLMw MySQL执行SQL会经过SQL解析和查询优化的过程,解析器 ...

  3. webpack打包教程(一)常用loader详解

    1.打包图片 // { // test: /\.(png|jpe?g|gif)$/i, // use: [{ // loader: 'file-loader', // options: { // na ...

  4. 使用selenium爬虫抓取数据

    写在前面 本来这篇文章该几个月前写的,后来忙着忙着就给忘记了.ps:事多有时候反倒会耽误事.几个月前,记得群里一朋友说想用selenium去爬数据,关于爬数据,一般是模拟访问某些固定网站,将自己关注的 ...

  5. HTML+CSS基础 border css属性 Div块 盒子

    border  css属性 边框颜色 border-color:red/#ffffff/rgb()默认为黑色 边框样式 border-style:solid (实线) dashed (虚线).默认为n ...

  6. 【Oracle】 RMAN命令汇总

    RMAN命令汇总 2013年写了关于RMAN命令的汇总,先转换为MD文档,温故而知新. 1.进入RMAN 进入本地数据库 [oracle@oracle-n1 ~]$ rman target / 进入远 ...

  7. Vue.js 源码分析(三十) 高级应用 函数式组件 详解

    函数式组件比较特殊,也非常的灵活,它可以根据传入该组件的内容动态的渲染成任意想要的节点,在一些比较复杂的高级组件里用到,比如Vue-router里的<router-view>组件就是一个函 ...

  8. 分布式中session共享的解决方案:spring-session

    Session是客户端与服务器通讯会话跟踪技术,是服务器与客户端保持整个通讯的会话基本信息.客户端在第一次访问服务器的时候,服务端会响应一个sessionId并且将它存入到本地的Cookie中,在之后 ...

  9. 【UOJ#74】【UR #6】破解密码

    [UOJ#74][UR #6]破解密码 题面 UOJ 题解 发现这个过程是一个字符串哈希的过程. 把第一位单独拿出来考虑,假设这个串是\(p+S\),旋转后变成了\(S+p\). 其哈希值分别是:\( ...

  10. 『字符合并 区间dp 状压dp』

    字符合并 Description 有一个长度为 n 的 01 串,你可以每次将相邻的 k 个字符合并,得到一个新的字符并获得一定分数.得到的新字符和分数由这 k 个字符确定.你需要求出你能获得的最大分 ...