[hdu6990]Directed Minimum Spanning Tree
模板题:在有向图中,对每一个点求以其为根的最小(外向)生成树
(当图是强连通时)可以使用朱刘算法,算法过程如下:
1.对每一个节点,选择指向该点的边权最小的边,即得到一张子图
2.任选这张子图的一个简单环,并对这个环执行以下操作——
(1)对于环上的边$(u,v)$,将所有以$v$为终点的边边权减去$(u,v)$的边权
(2)新建一个点为将环上所有点合并后的结果,并删除新点的自环
3.重复此过程,直至仅剩下一个点
(不难证明第1步中每一个点入度都非0,第2步中一定存在一个环)
在此过程中,再另外维护一棵树:在第2.(2)中,环上的每一个点向新建的点连一条边权为其对应边(即环上指向该点的边)的边权的边,显然这是一棵内向树,且根即为最后剩下的节点
此时,每一个节点的答案即树上的边权和-其到根路径上的边权和
下面,问题即如何(快速)实现之前的过程——
先对每一个点的边集(指到该点的边)维护一个可并堆,显然即可支持1的查询和2.(2)的合并,2.(1)的修改也可以用懒标记实现
此时,考虑从任意一点dfs,由于每一个点入度都非0,那么不断选择"指向自己的边权最小的边",当重复访问一个节点时即可进行缩点,缩点后继续递归即可
另外,图并不一定强连通,这个问题可以通过加入边$(1,2,\infty),(2,3,\infty),...,(n,1,\infty)$来解决,若最终某个点的答案为$\infty$即说明不存在以该点为根的生成树,进而图即变为强连通的
综上,总复杂度为$o(n\log n)$,可以通过


1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 #define ll long long
5 #define ull unsigned ll
6 #define pil pair<int,ll>
7 #define fi first
8 #define se second
9 vector<int>v[N<<1];
10 int V,t,n,m,x,y,z,rt[N],ls[N<<1],rs[N<<1],fa[N],st[N],vis[N];
11 ll tag[N<<1],Val[N];
12 ull ans[N];
13 pil val[N<<1],pos[N];
14 int find(int k){
15 if (k==fa[k])return k;
16 return fa[k]=find(fa[k]);
17 }
18 void upd(int k,ll x){
19 tag[k]+=x,val[k].se+=x;
20 }
21 void down(int k){
22 if (!tag[k])return;
23 if (ls[k])upd(ls[k],tag[k]);
24 if (rs[k])upd(rs[k],tag[k]);
25 tag[k]=0;
26 }
27 int New(int x,ll z){
28 int k=++V;
29 ls[k]=rs[k]=tag[k]=0;
30 val[k]=make_pair(x,z);
31 return V;
32 }
33 int merge(int k1,int k2){
34 if ((!k1)||(!k2))return k1+k2;
35 if (val[k1].se>val[k2].se)swap(k1,k2);
36 down(k1);
37 rs[k1]=merge(rs[k1],k2);
38 swap(ls[k1],rs[k1]);
39 return k1;
40 }
41 void add(int x,int y,ll z){
42 rt[y]=merge(rt[y],New(x,z));
43 }
44 void del(int x){
45 down(rt[x]);
46 rt[x]=merge(ls[rt[x]],rs[rt[x]]);
47 }
48 void dfs(int x,ull s){
49 if (x<=n)ans[x]=s;
50 for(int i=0;i<v[x].size();i++)dfs(v[x][i],s-Val[v[x][i]]);
51 }
52 int main(){
53 scanf("%d",&t);
54 while (t--){
55 scanf("%d%d",&n,&m);
56 V=st[0]=ans[0]=0;
57 for(int i=1;i<=(n<<1);i++){
58 fa[i]=i;
59 rt[i]=vis[i]=0;
60 v[i].clear();
61 }
62 for(int i=1;i<=m;i++){
63 scanf("%d%d%d",&x,&y,&z);
64 add(x,y,z);
65 }
66 for(int i=1;i<=n;i++)add(i,i%n+1,1e14);
67 st[++st[0]]=1,vis[1]=1;
68 int nn=n;
69 while (1){
70 x=st[st[0]];
71 while ((rt[x])&&(find(val[rt[x]].fi)==x))del(x);
72 if (!rt[x])break;
73 y=find(val[rt[x]].fi);
74 Val[x]=val[rt[x]].se,del(x);
75 if (rt[x])upd(rt[x],-Val[x]);
76 if (!vis[y]){
77 st[++st[0]]=y,vis[y]=1;
78 continue;
79 }
80 nn++;
81 while (1){
82 v[nn].push_back(x);
83 fa[x]=nn,rt[nn]=merge(rt[nn],rt[x]);
84 if (x==y){
85 st[st[0]]=nn,vis[nn]=1;
86 break;
87 }
88 x=st[--st[0]];
89 }
90 }
91 for(int i=1;i<nn;i++)ans[0]+=Val[i];
92 dfs(nn,ans[0]);
93 for(int i=1;i<=n;i++){
94 if (ans[i]>1e14)printf("-1\n");
95 else printf("%llu\n",ans[i]);
96 }
97 }
98 return 0;
99 }
[hdu6990]Directed Minimum Spanning Tree的更多相关文章
- 【HDU 4408】Minimum Spanning Tree(最小生成树计数)
Problem Description XXX is very interested in algorithm. After learning the Prim algorithm and Krusk ...
- 数据结构与算法分析–Minimum Spanning Tree(最小生成树)
给定一个无向图,如果他的某个子图中,任意两个顶点都能互相连通并且是一棵树,那么这棵树就叫做生成树(spanning tree). 如果边上有权值,那么使得边权和最小的生成树叫做最小生成树(MST,Mi ...
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge LCA/(树链剖分+数据结构) + MST
E. Minimum spanning tree for each edge Connected undirected weighted graph without self-loops and ...
- CF# Educational Codeforces Round 3 E. Minimum spanning tree for each edge
E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...
- Codeforces Educational Codeforces Round 3 E. Minimum spanning tree for each edge LCA链上最大值
E. Minimum spanning tree for each edge 题目连接: http://www.codeforces.com/contest/609/problem/E Descrip ...
- MST(Kruskal’s Minimum Spanning Tree Algorithm)
You may refer to the main idea of MST in graph theory. http://en.wikipedia.org/wiki/Minimum_spanning ...
- HDU 4408 Minimum Spanning Tree 最小生成树计数
Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- [Educational Round 3][Codeforces 609E. Minimum spanning tree for each edge]
这题本来是想放在educational round 3的题解里的,但觉得很有意思就单独拿出来写了 题目链接:609E - Minimum spanning tree for each edge 题目大 ...
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树+树链剖分+线段树
E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...
随机推荐
- 痞子衡嵌入式:我的三个小项目陆续上线恩智浦官方Github
恍如眨眼间,痞子衡在飞思卡尔/恩智浦已经工作 8 年多了,前 5 年主要是在软件团队,最近 3 年在系统团队.所处团队不同,工作思维也不同,自从转到系统团队,开始跟客户打起交道,对待问题和解决问题的立 ...
- efcore分表分库原理解析
ShardingCore ShardingCore 易用.简单.高性能.普适性,是一款扩展针对efcore生态下的分表分库的扩展解决方案,支持efcore2+的所有版本,支持efcore2+的所有数据 ...
- Stream之高级函数
上回文说到了有关Stream一些数学函数的用法.今天来说下Stream一些高级的函数用法,这些函数在日常工作中也是必不可少的,测试数据还是引用上一篇的数据. Map 这个方法我个人称之为转换函数,把一 ...
- Linux 下 xargs 命令
xargs 常常被大家忽略的一个命令,对它的一些用法很多人可能不熟悉,其实它是一个功能强大的命令,特别是在结合管道进行批量处理方面 语法 xargs 语法格式如下 xargs [OPTION]... ...
- DistSQL:像数据库一样使用 Apache ShardingSphere
Apache ShardingSphere 5.0.0-beta 深度解析的第一篇文章和大家一起重温了 ShardingSphere 的内核原理,并详细阐述了此版本在内核层面,特别是 SQL 能力方面 ...
- 洛谷1429 平面最近点对(KDTree)
qwq(明明可以直接分治过掉的) 但是还是当作联系了 首先,对于这种点的题,很显然的套路,我们要维护一个子树\(mx[i],mn[i]\)分别表示每个维度的最大值和最小值 (这里有一个要注意的东西!就 ...
- Spirit带你了解如何安全引入第三方资源
Spirit带你了解如何安全的引入第三方资源 本文介绍一下如何安全的引入第三方资源 同源策略(SOP) 首先我们来了解一下什么是同源策略,下面的是wiki百科的定义 同源策略是指Web浏览器中,允许某 ...
- 脚本注入3(blind)
布尔盲注适用于任何情况回显都不变的情况. (由此,可以看出,回显啥的其实都不重要,最重要的是判断注入点.只要找到注入点了,其他的都是浮云.) 在操作上,时间盲注还稍微简单一点:它不需要像布尔盲注那样, ...
- 对比7种分布式事务方案,还是偏爱阿里开源的Seata,真香!(原理+实战)
前言 这是<Spring Cloud 进阶>专栏的第六篇文章,往期文章如下: 五十五张图告诉你微服务的灵魂摆渡者Nacos究竟有多强? openFeign夺命连环9问,这谁受得了? 阿里面 ...
- 求求你了,用Docker吧
这是一个开始使用 Docker 的 Tutorial 大无语事件发生!大数据课实验课要用到Hadoop,实验指导是在一个Ubuntu虚机上通过安装包安装Hadoop并运行一个词频统计程序,整个实验就是 ...