前言:對於這週的咕咕咕表示好像沒什麼好表示的,完全沒有靈感a......寫東西真的好難啊......於是又玩了半天鬼泣4???還挺好玩的

來源:題解


题目背景

缩点+DP

题目描述

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

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

输入输出格式

输入格式:

第一行,n,m

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

第三至m+2行,每行两个整数u,v,表示u->v有一条有向边

输出格式:

共一行,最大的点权之和。

输入输出样例

输入样例#1:

2 2
1 1
1 2
2 1
输出样例#1:

2

说明

n<=10^4,m<=10^5,点权<=1000

算法:Tarjan缩点+DAGdp


題目中給出了算法,然而第一篇題解用的是拓撲排序,所以我就照著抄了......

本來寒假學過tarjan的,然而忘記了,這次複習一開始最看不懂的是low數組:

low數組表示“從i點出發能訪問到的最早進入時間”,事實上是如果從i點出發能向上走到某個點說明這裡存在了一個環,從i發出了一條後向邊,

等dfs完這個點的分支的時候,找到的環就會是最大的了。

縮點就是每個強連通分量當做一個點,然後重新建圖

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=+;
int n,m,cnt,tim,top,s;
int p[maxn],head[maxn],sd[maxn],dfn[maxn],low[maxn];
//sd為這個點在哪個強連通分量中,dfs時間戳,
//low棧中以u為父結點的子樹能連接到棧中最上端的點的dfs值
//也就是從i點出發能訪問到的最早進入時間
//p為點權,in為入度
int stac[maxn],vis[maxn];//栈只为了表示此时是否有父子关系
int h[maxn],in[maxn],dist[maxn];
struct node{
int u,v,next;
}e[maxn*],ed[maxn*];
void add(int u,int v)
{
e[++cnt].u=u;
e[cnt].v=v;
e[cnt].next=head[u];
head[u]=cnt;
}
void tarjan(int x)//求強連通分量,每個強連通分量就是一個新點
{
low[x]=dfn[x]=++tim;
stac[++top]=x;vis[x]=; for(int i=head[x];i;i=e[i].next){
int v=e[i].v;
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if(vis[v]){
low[x]=min(low[x],low[v]);
}
}
if(dfn[x]==low[x]){
int y;
while(y=stac[top--]){
sd[y]=x;
vis[y]=;
if(x==y)break;
p[x]+=p[y];
}
}
}
//縮成了DAG圖,所以可以拓撲排序了
//可以直接dp
int topo()
{
queue<int>q;
int tot=;
for(int i=;i<=n;i++)
if(sd[i]==i&&!in[i]){//自己是這個強連通分量的根
q.push(i);
dist[i]=p[i];
}
while(!q.empty()){
int k=q.front();q.pop();
for(int i=h[k];i;i=ed[i].next){
int v=ed[i].v;
dist[v]=max(dist[v],dist[k]+p[v]);
in[v]--;
if(in[v]==)q.push(v);
}
}
int ans=;
for(int i=;i<=n;i++)
ans=max(ans,dist[i]);
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d",&p[i]);
for(int i=;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}
for(int i=;i<=n;i++)
if(!dfn[i])tarjan(i);
for(int i=;i<=m;i++){//重新建圖,枚舉每一條原邊,如果不在一個強連通分量里就連上
int x=sd[e[i].u],y=sd[e[i].v];
if(x!=y){
ed[++s].next=h[x];
ed[s].v=y;
ed[s].u=x;
h[x]=s;
in[y]++;
}
}
printf("%d",topo());
}

[模板](luogu P3387)縮點的更多相关文章

  1. 【Luogu P3387】缩点模板(强连通分量Tarjan&拓扑排序)

    Luogu P3387 强连通分量的定义如下: 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶 ...

  2. [題解](縮點)luogu_P2341受歡迎的牛

    對於每個強聯通分量,這些牛一定都互相喜歡,所以縮點(我也不知道怎麼想到的) 接下來就是統計答案,最後縮成了一個DAG圖,如果這個點是明星的話,其他每個點一定直接或間接的鏈接這個點 也就是說其他點一定有 ...

  3. 解题报告+板子:luogu P3387 【模板】缩点

    题目链接:P3387 [模板]缩点 缩点板子,所谓\(dp\)就是拓扑排序(毕竟可以重走边),像\(SPFA\)一样松弛就好,就是重边极其烦人,还加了排序(绝对自己想的,然鹅拓扑的思路不是). 下面上 ...

  4. luogu P3387 【模板】缩点

    题目 好久没法博客了 这次就水个板子题目吧 tarjan缩点之后重新建图 而且边权应该都是正的(要不我怎么能这么轻松水过去) 在新图上记忆化一下就好了 f[i] 表示 开头选i这个点 的 路径最大值 ...

  5. luogu P3387 【模板】缩点_拓扑排序

    还是很好些的. Code: #include <stack> #include <cstdio> #include <algorithm> #include < ...

  6. LUOGU P3387 【模板】缩点 (缩点+DAG dp)

    解题思路 缩点后按拓扑排序跑一个dp. #include<iostream> #include<cstdio> #include<cstring> #include ...

  7. 高精度模板 Luogu P1932 A+B & A-B & A*B & A/B Problem

    P1932 A+B & A-B & A*B & A/B Problem 题目背景 这个题目很新颖吧!!! 题目描述 求A.B的和差积商余! 输入输出格式 输入格式: 两个数两行 ...

  8. 基数排序模板[luogu 1177]

    #include<bits/stdc++.h> #define LL long long using namespace std; ,bas=; ]; LL idx(LL k,LL w) ...

  9. 平面最近点对模板[luogu P1429]

    %:pragma GCC optimize() #include<bits/stdc++.h> #define DB double #define m (((l)+(r))>> ...

随机推荐

  1. React + fetch API + 百度地图api + 跨域 填坑

    做项目遇到一个百度地图api 的跨域问题.由于使用fetch ,在调用类似 http://api.map.baidu.com/geocoder/v2/callback=renderReverse&am ...

  2. 浅淡!important对CSS的重要性

    SS中的!important是一个非常重要的属性,有时候发挥着非常大的作用,52CSS.com这方面的知识并不是非常多,我们看下面的文章,对它作比较感观的了解. 前几天写一些CSS代码的时候又难为我了 ...

  3. [RK3288][Android6.0] 调试笔记 --- eMMC分区号和名字的对应【转】

    本文转载自:http://blog.csdn.net/kris_fei/article/details/77318410 Platform: Rockchip OS: Android 6.0 Kern ...

  4. 青岛理工ACM交流赛 J题 数格子算面积

    数格子算面积 Time Limit: 1000MS Memory limit: 262144K 题目描述 给你一个多边形(用’\’和’/’表示多边形的边),求多边形的面积. 输入  第一行两个正整数h ...

  5. LightOJ - 1027 A Dangerous Maze —— 期望

    题目链接:https://vjudge.net/problem/LightOJ-1027 1027 - A Dangerous Maze    PDF (English) Statistics For ...

  6. GDP与股市市值

    巴菲特提出一个判断市场估值高低的原则:市场总市值与GDP之比的高低,反映了市场投资机会和风险度.如果所有上市公司总市值占GDP的比率在70%-80%之间,则买入股票长期而言可能会让投资者有相当不错的报 ...

  7. VirtualBox下安装ubuntu图文教程以及软件安装

    一. 下载安装VirtualBox 官网下载VirtualBox,目前版本:VirtualBox 5.1.8 for Windows hosts x86/amd64 下载好了安装VirtualBox, ...

  8. Android Studio工程Gradle编译报错

    一.环境的搭建: 首先搭建好AndroidStudio环境.我使用的是Ubuntu 12.04系统(由于此机器还要运行其他程序,为避免兼容性问题,暂未更新到最新,而继续沿用此稳定版),java和jdk ...

  9. DTP模型之二:(XA协议之二)jotm分布式事务实现

    分布式事务是指操作多个数据库之间的事务,spring的org.springframework.transaction.jta.JtaTransactionManager,提供了分布式事务支持.如果使用 ...

  10. Azkaban简介和使用

    概述 为什么需要工作流调度系统 l 一个完整的数据分析系统通常都是由大量任务单元组成: shell脚本程序,java程序,mapreduce程序.hive脚本等 l 各任务单元之间存在时间先后及前后依 ...