模板题:在有向图中,对每一个点求以其为根的最小(外向)生成树

(当图是强连通时)可以使用朱刘算法,算法过程如下:

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的更多相关文章

  1. 【HDU 4408】Minimum Spanning Tree(最小生成树计数)

    Problem Description XXX is very interested in algorithm. After learning the Prim algorithm and Krusk ...

  2. 数据结构与算法分析–Minimum Spanning Tree(最小生成树)

    给定一个无向图,如果他的某个子图中,任意两个顶点都能互相连通并且是一棵树,那么这棵树就叫做生成树(spanning tree). 如果边上有权值,那么使得边权和最小的生成树叫做最小生成树(MST,Mi ...

  3. 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 ...

  4. 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 ...

  5. 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 ...

  6. 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 ...

  7. HDU 4408 Minimum Spanning Tree 最小生成树计数

    Minimum Spanning Tree Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  8. [Educational Round 3][Codeforces 609E. Minimum spanning tree for each edge]

    这题本来是想放在educational round 3的题解里的,但觉得很有意思就单独拿出来写了 题目链接:609E - Minimum spanning tree for each edge 题目大 ...

  9. 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 ...

随机推荐

  1. 洛谷4366——最短路(dijkstra,思维,异或)

    题目大意 给定一个n个点,m条边的图,每条边有边权,而每个点\(i\)也可以直接到达\(j\),代价是\(i\ xor\ j\),给定一个S和T,求S到T的最小代价 其中\(n\le100000,m\ ...

  2. JAR文件

    目录 JAR文件 创建JAR文件 jar程序选项 清单文件 注释 可执行JAR文件 警告 多版本JAR文件 注释 关于命令行选项的说明 警告 警告 JAR文件 在将应用程序打包时,你一定希望只向用户提 ...

  3. 掌握BeanShell,轻松处理jmeter中的数据

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15424558.html 博客主页:https://www.cnblogs.com/testero ...

  4. 款阿里开源的 Java 诊断工具Arthas

    Arthas是什么鬼? Arthas是一款阿里巴巴开源的 Java 线上诊断工具,功能非常强大,可以解决很多线上不方便解决的问题. Arthas诊断使用的是命令行交互模式,支持JDK6+,Linux. ...

  5. HashMap、ConcurrentHashMap红黑树实现分析

    本文学习知识点 1.二叉查找树,以及二叉树查找带来的问题. 2.平衡二叉树及好处. 3.红黑树的定义及构造. 4.ConcurrentHashMap中红黑树的构造. 在正式分析红黑树之前,有必要了解红 ...

  6. UnboundLocalError: local variable 'range' referenced before assignment

    1. 报错信息 UnboundLocalError: local variable 'range' referenced before assignment 2. 代码 class Car(): &q ...

  7. LeetCode:链表专题

    链表专题 参考了力扣加加对与链表专题的讲解,刷了些 leetcode 题,在此做一些记录,不然没几天就没印象了 出处:力扣加加-链表专题 总结 leetcode 中对于链表的定义 // 定义方式1: ...

  8. [对对子队]会议记录5.14(Scrum Meeting1)

    今天已完成的工作 何瑞 ​ 工作内容:初步完成循环指令系统 ​ 相关issue:实现循环语句系统的逻辑 ​ 相关签入:feat:循环语句的指令编辑系统初步完成 吴昭邦 ​ 工作内容:将流水线系统和循环 ...

  9. CSP2021 翻车记

    DAY - INF 日常模拟赛被吊打,不知道为啥总是出一些小问题导致正解gg,成绩的话也就是中游吧,不过方差不小 DAY - 2 感冒了,头疼得很,签到题甚至也签到失败了,烦得很 DAY -1 全真体 ...

  10. 写一段java程序来执行linux命令

    摘要 在日常开发中,程序员需要经常查询服务器日志来排查问题和调试程序.如果是本地调试还好,但项目一旦发布到服务器上,每次查日志就很麻烦,而且日志量巨大,有时我们无法找到我们需要的信息.经常需要借助第三 ...