缩点,就是把一张有向有环图中的环缩成一个个点,形成一个有向无环图。

首先我介绍一下为什么这题要缩点(有人肯定觉得这是放屁,这不就是缩点的模板题吗?但我们不能这么想,考试的时候不会有人告诉你打什么板上去吧)

根据题目意思,我们只需要找出一条点权最大的路径就行了,不限制点的个数。那么考虑对于一个环上的点被选择了,一整条环是不是应该都被选择,这一定很优,能选干嘛不选。很关键的是题目还允许我们重复经过某条边或者某个点,我们就不需要考虑其他了。因此整个环实际上可以看成一个点(选了其中一个点就应该选其他的点)

那么就正式开始缩环为点了。当然了,首先肯定是找环,为大家推荐两篇博客(不是我宣传,这两篇博客也只是我找的[] (http://blog.csdn.net/acmmmm/article/details/16361033))[](http://blog.csdn.net/sentimental_dog/article/details/53790582)

希望博客被我转载的博主不要介意。

看看这两篇博客,我觉得大家就有了一个基本认识了。在缩点操作中,最重要的是维护三个东西,它们在我代码里分别是stac(栈)(ps:之所以不加k是因为万能头文件的荼毒),dfn(时间戳),low(够追溯到的最早的栈中节点的次序号),详细的解释在代码注释里。

下面就是考虑对这三个东西的运用。详细参考博客(博客带图),需要注意的是,当dfn[u]==low[u]时,表明u一定是环上的一点,且环上的其他点就是u的子树。为什么呢?看代码
low[x]=dfn[x]=++tim;

low[x]=min(low[x],low[v]);

我截取了两句代码,第一句是对点x的low,dfn的初始化。在之后的操作中,low[x]始终取自己子树low[v]的较小值,那么什么情况会使得dfn[u]又“重新”和low[u]相等呢,就是在u的子树中有一条边(就是博客1中的后向边)直接指回了u。这样不就是形成了一个环了吗?

之后就是把环上所有的点的sd都变成这个u,即用u代替整个环,并把权值集中在u上

还有值得注意的,这个栈表示的究竟是什么?(这个在博客1中也有),根据我的理解表示的是当前搜索的一条链上的一个个点吧。

下面我附上代码先

#include<bits/stdc++.h>
using namespace std; const int maxn=+;
int n,m,sum,tim,top,s;
int p[maxn],head[maxn],sd[maxn],dfn[maxn],low[maxn];//DFN(u)为节点u搜索被搜索到时的次序编号(时间戳),Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号
int stac[maxn],vis[maxn];//栈只为了表示此时是否有父子关系
int h[maxn],in[maxn],dist[maxn];
struct EDGE
{
int to;int next;int from;
}edge[maxn*],ed[maxn*];
void add(int x,int y)
{
edge[++sum].next=head[x];
edge[sum].from=x;
edge[sum].to=y;
head[x]=sum;
}
void tarjan(int x)
{
low[x]=dfn[x]=++tim;
stac[++top]=x;vis[x]=;
for (int i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
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];
}
}
}
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].to;
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[edge[i].from],y=sd[edge[i].to];
if (x!=y)
{
ed[++s].next=h[x];
ed[s].to=y;
ed[s].from=x;
h[x]=s;
in[y]++;
}
}
printf("%d",topo());
return ;
}

在处理了环后,我们就重新建立一张图,以每个环为节点(孤立一个点也算也算环的,其实也就是强联通分量了)。在这张图中我们要dp,显然对于任意边<u,v>,dp[v]=max(dp[v],dp[u]+p[v]),p[v]是v是这个环的总权值。

那么怎么解决无后效性问题呢?答案就是拓扑排序,至于为什么,在我的另一篇题解里我有提及。这下我有安利嫌疑了,但我还是希望大家去看一看,下面我附上链接。

这也是一篇题解,其实主要讲的就是拓扑排序解决DP的无后效性问题了

图论之tarjan缩点的更多相关文章

  1. 图论算法-Tarjan模板 【缩点;割顶;双连通分量】

    图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; ...

  2. 洛谷 P2194 HXY烧情侣【Tarjan缩点】 分析+题解代码

    洛谷 P2194 HXY烧情侣[Tarjan缩点] 分析+题解代码 题目描述: 众所周知,HXY已经加入了FFF团.现在她要开始喜(sang)闻(xin)乐(bing)见(kuang)地烧情侣了.这里 ...

  3. hihoCoder 1185 连通性·三(Tarjan缩点+暴力DFS)

    #1185 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出 ...

  4. POJ 1236 Network of Schools(Tarjan缩点)

    Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16806   Accepted: 66 ...

  5. King's Quest —— POJ1904(ZOJ2470)Tarjan缩点

    King's Quest Time Limit: 15000MS Memory Limit: 65536K Case Time Limit: 2000MS Description Once upon ...

  6. 【BZOJ-2438】杀人游戏 Tarjan + 缩点 + 概率

    2438: [中山市选2011]杀人游戏 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1638  Solved: 433[Submit][Statu ...

  7. 【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP

    1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 787  Solved: 318[Submit][Stat ...

  8. 【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点

    1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1685  Solved: 724[Submit] ...

  9. BZOJ 1051 受欢迎的牛(Tarjan缩点)

    1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4573  Solved: 2428 [Submit][S ...

随机推荐

  1. caffe训练CIFAR数据库

    CIFAR-10是一个用于普适物体识别的数据集.Cifar-10由60000张32*32的RGB彩色图片构成,50000张训练图片,10000张测试图片,分为10类.cifar下载地址: http:/ ...

  2. Oracle Hint的用法

    1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化. 例如: SELECT /*+ALL+_ROWS*/ EMP_NO,EMP_NAM,DAT_I ...

  3. 杂项-编程:AOP(面向切面编程)

    ylbtech-杂项-编程:AOP(面向切面编程) 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一 ...

  4. centos 出现的问题

    1.DNS问题,导致yum没得源 echo "nameserver 8.8.8.8">>/etc/resolv.conf 2.CentOS 7最小化安装后找不到‘ifc ...

  5. 压力测试工具 Tinyget

    Tinyget 压力测试工具使用方法为:命令行切换到工具所在路径下,然后输入压力命令.如:tinyget -srv:localhost -uri:/FeaturedProdu1cts.aspx -th ...

  6. 自定义view 之多个引导层动画效果

    SupernatantView 如果我英文还可以的话这个应该叫做漂浮在上层的view---引导层 今天闲来无事看了网上的一些引导层案例总感觉如果不是很舒服,就是类似于很死板的显示和消失 我在想能不能弄 ...

  7. ListView的Item动画

    1.效果图 2.需求就是点击item歌曲时,实现一种飞入到预约按钮处的效果 3.思路:在布局文件中加入了一个条目布局,和listView的item一样,点击listView的item时,使用给条目布局 ...

  8. 史上最低,低到尘埃,CDR邀你一起嗨购618

    盼呀盼,望穿秋水~盼呀盼,何时降价~ 6.4开始,CDR X6全民狂欢618放价活动全面开启 力度之大,范围之广,时间之久,价格之低,都是前所未有的 不负众望,这个618,CDR真的做到一降到底,没有 ...

  9. 洛谷P2915 [USACO08NOV]奶牛混合起来Mixed Up Cows 状压动归

    考场上空间开大了一倍就爆0了QAQ- Code: #include<cstdio> #include<algorithm> #include<cmath> usin ...

  10. 装饰器阶段性练习(题目)[转载http://www.cnblogs.com/linhaifeng/p/7278389.html]

    # 一:编写函数,(函数执行的时间是随机的)# 二:编写装饰器,为函数加上统计时间的功能# 三:编写装饰器,为函数加上认证的功能## 四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件 ...