描述:https://www.luogu.com.cn/problem/P3387

给定一个 nn 个点 mm 条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。

允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次.


#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int maxn=;
int n,m,p[maxn],dp[maxn];
struct edge{
int u,to,nxt;
}d[maxn*];int head[maxn*],cnt=;
void add(int u,int v){
d[cnt].u=u,d[cnt].to=v,d[cnt].nxt=head[u],head[u]=cnt++;
}
int dfn[maxn],low[maxn],id,stack[maxn],vis[maxn],top,sd[maxn];//为tarjan准备
void tarjan(int now)
{
dfn[now]=low[now]=++id;
stack[++top]=now,vis[now]=;
for(int i=head[now];i;i=d[i].nxt)
{
int w=d[i].to;
if(!dfn[w])
tarjan(w),low[now]=min(low[now],low[w]);
else if(vis[w])
low[now]=min(low[now],low[w]);
}
if(low[now]==dfn[now])
{
int temp;
while(temp=stack[top--])
{
sd[temp]=now;
vis[temp]=;
if(temp==now) break;
p[now]+=p[temp];//集中在now这个超级点上
}
}
}
int indug[maxn];
vector<int>vec[maxn];
int tuopu()
{
queue<int>q;
for(int i=;i<=n;i++) if(!indug[i]&&sd[i]==i) q.push(i),dp[i]=p[i];
while(!q.empty())
{
int now=q.front();q.pop();
for(int i=;i<vec[now].size();i++)
{
int w=vec[now][i];
dp[w]=max(dp[w],dp[now]+p[w]);
if(--indug[w]==) q.push(w);
}
}
int ans=;
for(int i=;i<=n;i++) ans=max(ans,dp[i]);
return ans;
}
int main()
{
cin>>n>>m;
for(int i=;i<=n;i++) cin>>p[i];//读入点权
for(int i=;i<=m;i++)
{
int l,r;cin>>l>>r;
add(l,r);
}
for(int i=;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=;i<=m;i++)
{
int x=sd[d[i].u],y=sd[d[i].to];//看看两头是否是连通分量
if(x!=y)//不是就建边
vec[x].push_back(y),indug[y]++;
}
cout<<tuopu();
return ;
}

还有割点的

为什么(“low[v]>=dfn[u],此时u就是割点”)??

因为后面的点无法回到u点之前

u就把两个部分分开来了

#include <bits/stdc++.h>
using namespace std;
const int maxn=;
struct edge{
int nxt,to;
}d[maxn];
int n,m,id,cnt=,ttp;
int head[maxn],dfn[maxn],low[maxn],cut[maxn];
void add(int u,int v){
d[cnt].to=v,d[cnt].nxt=head[u],head[u]=cnt++;
}
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++id;
int child=;
for(int i=head[u];i;i=d[i].nxt)
{
int w=d[i].to;
if(!dfn[w])
{
tarjan(w,fa);
low[u]=min(low[u],low[w]);
if(low[w]>=dfn[u]&&u!=fa)//通过非非节点更新的low[w]
//因为在本连通块能回溯最多到dfn[u]
cut[u]=;
if(u==fa) child++;
}
low[u]=min(low[u],dfn[w]);
}
if(child>=&&u==fa) cut[u]=;
}
int main()
{
cin>>n>>m;
for(int i=;i<=m;i++)
{
int l,r;
cin>>l>>r;
add(l,r);add(r,l);
}
for(int i=;i<=n;i++)
if(!dfn[i]) tarjan(i,i);
int ans=;
for(int i=;i<=n;i++)
if(cut[i]) ans++;
cout<<ans<<endl;
for(int i=;i<=n;i++)
if(cut[i])
cout<<i<<" ";
return ;
}

Tarjan缩点割点(模板)的更多相关文章

  1. tarjan 缩点(模板)

    描述: 给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 注:允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次. 思路: ...

  2. Tarjan缩点【模板】

    #include <algorithm> #include <cstdio> #include <map> using namespace std; ); map& ...

  3. Tarjan总结(缩点+割点(边)+双联通+LCA+相关模板)

    Tarjan求强连通分量 先来一波定义 强连通:有向图中A点可以到达B点,B点可以到达A点,则称为强连通 强连通分量:有向图的一个子图中,任意两个点可以相互到达,则称当前子图为图的强连通分量 强连通图 ...

  4. tarjan求强连通分量+缩点+割点以及一些证明

    “tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄>   自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...

  5. tarjan求强连通分量+缩点+割点/割桥(点双/边双)以及一些证明

    “tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄>   自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...

  6. Tarjan的缩点&&割点概述

    What is Tarjan? Tarjan,是一种用来解决图的联通性的一种有效途径,它的一般俗称叫做:缩点.我们首先来设想一下: 如果我们有一个图,其中A,B,C构成一个环,那么我们在某种条件下,如 ...

  7. HDU4738 tarjan割边|割边、割点模板

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=4738 坑点: 处理重边 图可能不连通,要输出0 若求出的结果是0,则要输出1,因为最少要派一个人 #inc ...

  8. Tarjan求强连通分量、求桥和割点模板

    Tarjan 求强连通分量模板.参考博客 #include<stdio.h> #include<stack> #include<algorithm> using n ...

  9. [模板]tarjan缩点+拓扑排序

    题目:给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大.你只需要求出这个权值和. 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次. 题目简述:先t ...

随机推荐

  1. 条件变量 condition_variable wait_for

    wait_for(阻塞当前线程,直到条件变量被唤醒,或到指定时限时长后) #include <iostream> #include <atomic> #include < ...

  2. 曹工说Redis源码(6)-- redis server 主循环大体流程解析

    文章导航 Redis源码系列的初衷,是帮助我们更好地理解Redis,更懂Redis,而怎么才能懂,光看是不够的,建议跟着下面的这一篇,把环境搭建起来,后续可以自己阅读源码,或者跟着我这边一起阅读.由于 ...

  3. vue2.x学习笔记(二十一)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12632730.html. 可复用性&结合-混入 基础 混入(mixin)提供了一种非常灵活的方式,来分发v ...

  4. winfrom 基础

    1 winfrom就是一种窗体开发端应用程序 2 窗体分类 1)记事本类:可以最大最小化,可以拖拽                                                窗体默 ...

  5. python数据分析工具——Pandas、StatsModels、Scikit-Learn

    Pandas Pandas是 Python下最强大的数据分析和探索工具.它包含高级的数据结构和精巧的工具,使得在 Python中处理数据非常快速和简单. Pandas构建在 Numpy之上,它使得以 ...

  6. 使用STM8S i2c对TPS65987寄存器进行读写

    上图是TPS65987的i2c读写协议,和标准i2c协议有点出入,不过也不难理解,在读的时候i2c slave在发送数据过来之前会先发送1byte数据表示后面会有几个字节数据过来,在写的时候i2c h ...

  7. js 一个或多个一维数组,算出元素之间相互组合的所有情况

    // 数据源 var target = { state1: ['1', '2'], state2: ['01', '02', '03'], state3: ['001','002'] } stackS ...

  8. <string>头文件常用成员函数

    之前说过 string和vector一样,也是一种顺序容器,并且它也自带成员函数,用法和vector的成员函数差不多,不过它只能用来存放字符,也就是字符串. 在c++中,<string>基 ...

  9. nav破解

    https://blog.csdn.net/qq_40529395/article/details/78839357

  10. 替换字符串sql

    update [表名] set 字段名 = replace(与前面一样的字段名,'原本内容','想要替换成什么') UPDATE `zjl_III_hei_zlj_20151111`.`ctrl_ne ...