热门标签 | HotTags
当前位置:  开发笔记 > 人工智能 > 正文

[BZOJ1093][ZJOI2007][Tarjan][DP]最大半联通子图

[题目][算法]Tarjan+DP[分析]易证一个强连通分量一定在最大半联通子图里面,所以先用tarjan缩点,然后图就变成了一个有向无环图。在这上面用(拓扑排序)dp的方法

[题目]

[算法]

Tarjan+DP

[分析]

易证一个强连通分量一定在最大半联通子图里面,所以先用tarjan缩点,然后图就变成了一个有向无环图。在这上面用(拓扑排序)dp的方法求出最长的链以及个数就可以了。但是要注意两个点(tarjan后)之间可能有多条边,而根据题目的意思这多条边只算一次方案(因为是导出子图),所以要注意判重(记录每个点上一次访问它的是谁,如果和当前点一样就跳过)

[代码]

/**************************************************************
Problem: 1093
User: gaotianyu1350
Language: C++
Result: Accepted
Time:2196 ms
Memory:33544 kb
****************************************************************/

#include
#include
#include
#include
#include
#include
using namespace std;

#define MAXN 100100
#define MAXM 1001000

struct graph
{
int point[MAXN],next[MAXM],v[MAXM];
int tot;
graph()
{
memset(point,0,sizeof(point));
memset(next,0,sizeof(next));
tot=0;
}
void addedge(int x,int y)
{
tot++;
next[tot]=point[x];point[x]=tot;v[tot]=y;
}
};

graph ori,last,relast;
int dfsTime[MAXN]={0},lowTime[MAXN]={0},st[MAXN]={0},duiying[MAXN]={0};
int rudu[MAXN]={0};
int f[MAXN]={0},fcnt[MAXN]={0};
int size[MAXN]={0};
int ctDfsTime=0,ctCOnnect=0,stTop=0;
int n,m,MOD;
int vis[MAXN]={0};
queue q;

void CheckMemory()
{
printf("%d\n",(sizeof(ori)*3+sizeof(dfsTime)+sizeof(lowTime)
+sizeof(st)+sizeof(duiying)+sizeof(rudu)+sizeof(f)+sizeof(fcnt)
+sizeof(size))/1000000);
}

void Tarjan(int now)
{
ctDfsTime++;
dfsTime[now]=lowTime[now]=ctDfsTime;
st[++stTop]=now;
for (int temp=ori.point[now];temp;temp=ori.next[temp])
if (!lowTime[ori.v[temp]])
{
Tarjan(ori.v[temp]);
lowTime[now]=min(lowTime[now],lowTime[ori.v[temp]]);
}
else
if (!duiying[ori.v[temp]])
lowTime[now]=min(lowTime[now],dfsTime[ori.v[temp]]);

if (dfsTime[now]==lowTime[now])
{
ctConnect++;
while (st[stTop]!=now)
size[ctConnect]++,duiying[st[stTop--]]=ctConnect;
stTop--;
duiying[now]=ctConnect,size[ctConnect]++;
}
}

void Rebuild()
{
for (int i=1;i<=n;i++)
for (int temp=ori.point[i];temp;temp=ori.next[temp])
if (duiying[i]!=duiying[ori.v[temp]])
{
last.addedge(duiying[i],duiying[ori.v[temp]]);
rudu[duiying[ori.v[temp]]]++;
relast.addedge(duiying[ori.v[temp]],duiying[i]);
}
for (int i=1;i<=ctConnect;i++)
if (!rudu[i])
{
q.push(i);
fcnt[i]=1;
f[i]=size[i];
}
}

void Dp()
{
int maxAns=0;
int cntAns=0;
while (!q.empty())
{
int now=q.front();q.pop();
for (int temp=relast.point[now];temp;temp=relast.next[temp])
{
int vv=relast.v[temp];
if (vis[vv]==now) continue;
if (f[vv]+size[now]>f[now])
{
f[now]=f[vv]+size[now];fcnt[now]=fcnt[vv]%MOD;
}
else
if (f[vv]+size[now]==f[now]) fcnt[now]=(fcnt[now]+fcnt[vv])%MOD;
vis[vv]=now;
}
for (int temp=last.point[now];temp;temp=last.next[temp])
{
rudu[last.v[temp]]--;
if (!rudu[last.v[temp]]) q.push(last.v[temp]);
}
if (f[now]>maxAns)
{
maxAns=f[now];cntAns=fcnt[now]%MOD;
}
else if (f[now]==maxAns)
cntAns=(cntAns+fcnt[now])%MOD;
}
printf("%d\n%d\n",maxAns,cntAns);
}

int main()
{
//freopen("input.txt","r",stdin);
//CheckMemory();
scanf("%d%d%d",&n,&m,&MOD);
for (int i=1;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ori.addedge(x,y);
}
for (int i=1;i<=n;i++)
if (!duiying[i])
Tarjan(i);
Rebuild();
Dp();
}




推荐阅读
  • 本文介绍如何使用Java实现AC自动机(Aho-Corasick算法),以实现高效的多模式字符串匹配。文章涵盖了Trie树和KMP算法的基础知识,并提供了一个详细的代码示例,包括构建Trie树、设置失败指针以及执行搜索的过程。 ... [详细]
  • 本文通过个人经历引出关于数学教学中的一个常见误解——被零除的结果,并深入探讨了浮点数中负零的存在及其背后的数学原理。 ... [详细]
  • 解决Xcode PBXcp 错误:找不到文件或目录
    当在Xcode中遇到PBXcp错误提示'No such file or directory'时,通常是由于文件引用问题导致的。本文将介绍两种有效的方法来解决这一常见问题。 ... [详细]
  • 本文探讨了Lua中元表和元方法的使用,通过具体的代码示例展示了如何利用这些特性来实现类似C语言中的运算符重载功能。 ... [详细]
  • Java数组面试常见问题及解析
    在Java编程面试中,数组作为基础且重要的知识点,经常成为考察的重点。本文将探讨数组的基础知识和相关面试题,帮助考生更好地准备面试。 ... [详细]
  • 本文介绍了一个基础算法题目,旨在通过求解特定范围内所有数字的阶乘之和来提升编程技能。重点在于理解和实现双重循环结构。 ... [详细]
  • 本文详细介绍了在使用Node.js处理JWT时遇到的'invalid algorithm'错误的解决方案。问题源于生成和验证token时使用的算法不一致,具体表现为生成token时使用HS256算法,而在验证时误用了RS256算法。 ... [详细]
  • 计算机视觉初学者指南:如何顺利入门
    本文旨在为计算机视觉领域的初学者提供一套全面的入门指南,涵盖基础知识、技术工具、学习资源等方面,帮助读者快速掌握计算机视觉的核心概念和技术。 ... [详细]
  • 【Java数据结构和算法】008栈
    目录0、警醒自己一、栈的应用场景和介绍1、栈的应用场景一个实际的场景:我的思考:2、栈的介绍入栈演示图:出栈演示图 ... [详细]
  • 深入理解Git与GitHub:分支管理与冲突解决
    本文详细探讨了Git中的分支管理技术,包括如何创建、切换和合并分支,以及如何有效解决分支合并时可能遇到的冲突。同时,文章还介绍了Git的基本原理,如哈希算法的应用和文件管理机制。 ... [详细]
  • 本章节深入讨论了线性光与感知均匀性的概念,强调了灰度图像中每个像素值如何反映视觉亮度的主观性质。文章进一步解析了亮度与光强度、辐射等物理量的区别,并探讨了这些概念在数字图像处理中的应用。 ... [详细]
  • 本文介绍了两种在MATLAB中用于识别和提取图像中封闭孔洞及其边界的高效方法。第一种方法通过图像填充和差分操作实现;第二种方法则基于Flood-Fill泛洪算法。 ... [详细]
  • 本文探讨了如何通过积累团队管理经验、促进团队成员的学习成长、建立公正的绩效考核体系以及明确奖惩机制来提升团队的整体效能。同时,文章还强调了领导者应具备的关键能力和如何通过团队成员的表现来评估领导者的管理水平。 ... [详细]
  • 多用户密码验证与加密登录系统
    本文介绍了一种基于多用户密码文件的加密登录方法,通过读取用户密码文件并使用简单的加密算法实现安全登录。文中详细描述了程序的设计思路及其实现过程。 ... [详细]
  • 本文通过一个经典问题——使用最少的老鼠在限定时间内找出含有毒药的瓶子,深入探讨了二分法的应用及其背后的逻辑原理。不仅展示了二分法在非传统排序问题中的有效应用,还扩展讨论了三分法的可能性与限制。 ... [详细]
author-avatar
暗恋达志_227
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有