[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 ...
随机推荐
- 洛谷4366——最短路(dijkstra,思维,异或)
题目大意 给定一个n个点,m条边的图,每条边有边权,而每个点\(i\)也可以直接到达\(j\),代价是\(i\ xor\ j\),给定一个S和T,求S到T的最小代价 其中\(n\le100000,m\ ...
- JAR文件
目录 JAR文件 创建JAR文件 jar程序选项 清单文件 注释 可执行JAR文件 警告 多版本JAR文件 注释 关于命令行选项的说明 警告 警告 JAR文件 在将应用程序打包时,你一定希望只向用户提 ...
- 掌握BeanShell,轻松处理jmeter中的数据
作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15424558.html 博客主页:https://www.cnblogs.com/testero ...
- 款阿里开源的 Java 诊断工具Arthas
Arthas是什么鬼? Arthas是一款阿里巴巴开源的 Java 线上诊断工具,功能非常强大,可以解决很多线上不方便解决的问题. Arthas诊断使用的是命令行交互模式,支持JDK6+,Linux. ...
- HashMap、ConcurrentHashMap红黑树实现分析
本文学习知识点 1.二叉查找树,以及二叉树查找带来的问题. 2.平衡二叉树及好处. 3.红黑树的定义及构造. 4.ConcurrentHashMap中红黑树的构造. 在正式分析红黑树之前,有必要了解红 ...
- UnboundLocalError: local variable 'range' referenced before assignment
1. 报错信息 UnboundLocalError: local variable 'range' referenced before assignment 2. 代码 class Car(): &q ...
- LeetCode:链表专题
链表专题 参考了力扣加加对与链表专题的讲解,刷了些 leetcode 题,在此做一些记录,不然没几天就没印象了 出处:力扣加加-链表专题 总结 leetcode 中对于链表的定义 // 定义方式1: ...
- [对对子队]会议记录5.14(Scrum Meeting1)
今天已完成的工作 何瑞 工作内容:初步完成循环指令系统 相关issue:实现循环语句系统的逻辑 相关签入:feat:循环语句的指令编辑系统初步完成 吴昭邦 工作内容:将流水线系统和循环 ...
- CSP2021 翻车记
DAY - INF 日常模拟赛被吊打,不知道为啥总是出一些小问题导致正解gg,成绩的话也就是中游吧,不过方差不小 DAY - 2 感冒了,头疼得很,签到题甚至也签到失败了,烦得很 DAY -1 全真体 ...
- 写一段java程序来执行linux命令
摘要 在日常开发中,程序员需要经常查询服务器日志来排查问题和调试程序.如果是本地调试还好,但项目一旦发布到服务器上,每次查日志就很麻烦,而且日志量巨大,有时我们无法找到我们需要的信息.经常需要借助第三 ...