P3387 【模板】缩点
题目背景
缩点+DP

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

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

输入格式
第一行两个正整数 n,m

第二行 n 个整数,依次代表点权

第三至 m+2 行,每行两个整数 u,vu,v,表示一条 u→v 的有向边。

输出格式
共一行,最大的点权之和。

输入输出样例
输入 #1复制
2 2
1 1
1 2
2 1
输出 #1复制
2
说明/提示
【数据范围】

算法:Tarjan 缩点 + DAGdp

思路:缩点,就是把一张有向有环图中的环缩成一个个点,形成一个有向无环图。
将有向有环图通过tarjan算法转换成缩点,再建图形成有向无环图(DAG),再拓扑排序,再dp。

方法一:拓扑排序+dp,dp直接点权

#include <bits/stdc++.h>
#define ll long longusing namespace std;
const int N=1e5+5;
int n,m,x[N],y[N],val[N],vis[N],dfn[N],low[N],dp[N];
int res[N],t=0,num=0,a[N],sum[N],in[N];
stack<int> s;
vector<int> v[N],v2[N],v3[N];void dfs(int x)
{dfn[x]=low[x]=++t;s.push(x);vis[x]=1;for(int i=0;i<v[x].size();i++){int y=v[x][i];if(!dfn[y]){dfs(y);low[x]=min(low[x],low[y]);}else if(vis[y])low[x]=min(low[x],low[y]);}if(low[x]==dfn[x]){num++;while(s.top()!=x){a[s.top()]=num;//队的编号sum[num]+=val[s.top()];//某个队的和vis[s.top()]=0;s.pop();}a[x]=num;sum[num]+=val[x];vis[x]=0;s.pop();}
}
void topo()
{int cnt=0;queue<int> q;for(int i=1;i<=num;i++)//编号if(in[i]==0)q.push(i);while(!q.empty()){int t=q.front();res[++cnt]=t;q.pop();for(int i=0;i<v2[t].size();i++){int y=v2[t][i];if(--in[y]==0)q.push(y);}}
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin >> n >> m;for(int i=1;i<=n;i++)cin >> val[i];for(int i=0;i<m;i++){cin >> x[i] >> y[i];v[x[i]].push_back(y[i]);}for(int i=1;i<=n;i++)//环变成缩点{if(!dfn[i])dfs(i);}for(int i=0;i<m;i++)//建新图{int x0=a[x[i]],y0=a[y[i]];if(x0!=y0){in[y0]++;v2[x0].push_back(y0);v3[y0].push_back(x0);//dp用到}}topo();int ans=0;for(int i=1;i<=num;i++)//dp,num个数{int x=res[i];//x表示编号dp[x]=sum[x];for(int j=0;j<v3[x].size();j++){int y=v3[x][j];dp[x]=max(dp[x],dp[y]+sum[x]);}ans=max(ans,dp[x]);}cout << ans << endl;return 0;
}

方法二:spfa,点权可变成边权

#include <bits/stdc++.h>using namespace std;
const int N=1e4+5;
int dfn[N],low[N],vis[N],a[N],n,m,x[10*N],y[10*N];
int sum[N],t=0,num=0,b[N],dis[N],vs[N],res=0;
vector<int> v[N],w[N];
stack<int> s;void dfs(int x)
{dfn[x]=low[x]=++t;s.push(x);vis[x]=1;for(int i=0;i<v[x].size();i++){int y=v[x][i];if(!dfn[y]){dfs(y);low[x]=min(low[x],low[y]);}else if(vis[y])low[x]=min(low[x],low[y]);}if(low[x]==dfn[x]){num++;while(s.top()!=x){b[s.top()]=num;//属于第几号连通分量sum[num]+=a[s.top()];//第几号连通分量的总和vis[s.top()]=0;s.pop();}b[x]=num;sum[num]+=a[x];vis[x]=0;s.pop();}
}
void spfa(int x)
{queue<int> q;memset(vs,0,sizeof(vs));memset(dis,0,sizeof(dis));vs[x]=1;dis[x]=sum[x];q.push(x);while(!q.empty()){int u=q.front();q.pop();vs[u]=0;for(int i=0;i<w[u].size();i++){int v=w[u][i];if(dis[v]<dis[u]+sum[v])//最长路,点权变边权{dis[v]=dis[u]+sum[v];if(vs[v])continue;vs[v]=1;q.push(v);}}}for(int i=1;i<=num;i++)res=max(res,dis[i]);
}
int main()
{cin >> n >> m;for(int i=1;i<=n;i++)cin >> a[i];for(int i=0;i<m;i++){cin >> x[i] >> y[i];v[x[i]].push_back(y[i]);}for(int i=1;i<=n;i++){if(!dfn[i])dfs(i);}for(int i=0;i<m;i++)//新建图{if(b[x[i]]!=b[y[i]]){w[b[x[i]]].push_back(b[y[i]]);}}for(int i=1;i<=num;i++)spfa(i);cout << res << endl;return 0;
}

P3387 【模板】缩点相关推荐

  1. 强连通分量:洛谷P3387 模板:缩点

    传送门 顾名思义,模板awa #include <cstdio> #include <cstring> #include <cmath> #include < ...

  2. 洛谷 P3387(缩点后+处理 )

    题目链接:https://www.luogu.com.cn/problem/P3387 分析: 我们需要找出一条点权最大的路径. 不限制点的个数,那么对于一个环上的点被选择了,一整条环都应该被选择. ...

  3. 洛谷3387 模板 缩点

    题目:缩点 思路:tarjan缩点+最长路. 注意: 1.用dijkstra求最长路时,优先队列中的<运算符要反过来. 2.需要把所有入度为0的点为起点跑一遍最长路. 3.每次求最长路时,dis ...

  4. 图论,专为迷途少年而生

    文章目录 目录 图的存储 邻接矩阵 前向星 Topsort P1038 神经网络 P1983 车站分级 最小生成树 MST 堆优化Prim 并查集Kruskal Matrix Tree Theory ...

  5. html标签属性可以省略,html部分---通用标签与属性;

    body的属性: bgcolor页面背景色:text文字颜色:topmargin上页边距:leftmargin左页边距:rightmargin右页边距:bottomargin下页边距: src是引用过 ...

  6. 图(八):强连通分量

    强连通分量 强连通分量是针对有向图来说的,当一个有向图中所有的点都能够相互到达则称这个图为强连通分量. 一.模板 int dfn[N], low[N], dfncnt, s[N], in_stack[ ...

  7. P3387 【模板】缩点 Tarjan强连通分量/树上dp

    P3387 [模板]缩点 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 首先,什么是强连通分量 极大强连通子图 叫做强连通分量             首先要明确,         ...

  8. (Tarjan)洛谷P3387【模板】缩点

    洛谷P3387[模板]缩点 思路: 虽然是缩点模板题,但是明显感觉比同一个题单中的其他题都难. 题目思路已经提供给你:Tarjan缩点+DAGdp.就是用Tarjan缩点,重新建图之后,边拓扑排序边建 ...

  9. P3387 【模板】缩点 洛谷 java题解 连通图+拓扑排序

    传送门: P3387 [模板]缩点 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P3387 问题分析 首先为了节省 ...

最新文章

  1. docred数据集情况笔记
  2. MySQL中的char和varchar类型
  3. 脚本的力量:MSDN中一段代码的IronPython与PowerShell实现
  4. XPATH获取USER列用户ID的小方法
  5. TreeList(一)
  6. 关闭蜂鸣最简单的方法
  7. VirtualBox的BUG:没超线程也认为有
  8. java io知识点汇总FIle类
  9. idea格式化代码失效
  10. 你不可不知的铠装光缆常识
  11. 工控行业学什么编程语言比较好_PLC五大主流编程语言你会几种?
  12. ODM、JDM、OEM、OBM
  13. #PixelConFi | 这个教师节,以投票代替祝福
  14. 在线转换pdf和虚拟打印机生成pdf文件操作攻略
  15. Excel数据分析从入门到精通(三)函数进阶-52个Excel函数之清洗类函数
  16. 我爷爷来了都能看懂的数据库主键,候选键,外键,非空和check的几种约束方式及使用方法
  17. 貝塞爾 Layer 入門指南
  18. 「BJOI 2019」奥术神杖
  19. iOS Tagged Pointer
  20. mes java_MES项目简单总结(技术篇)

热门文章

  1. ChatGPT初体验——开发好帮手
  2. UBI文件系统(转)
  3. Unity中的3D数学—02向量与矩阵
  4. 在电脑上打开手机当前浏览的网页
  5. 关于kali Linux缺少pyrit或者pyrit无法定位的问题
  6. 【汇正财经】大盘低开回升
  7. HHDBCS的快捷命令使用
  8. python进行大小写转换
  9. 怎么在手机上赚钱?分享5个赚钱方法,生活费是足够了!
  10. 网络学习之网络通信设备辨析