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

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

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. 学习使用Wpf开源的文本编辑器—smithhtmleditor

    前言 本文主要介绍使用Wpf文本编辑器--smithhtmleditor. 编辑器使用 首先新建一个项目WpfEditor. 然后到Codeplex下载smithhtmleditor. 下载地址:ht ...

  2. 教你轻松构建基于 Serverless 架构的小程序

    前言 自 2017 年第一批小程序上线以来,越来越多的移动端应用以小程序的形式呈现.小程序触手可及.用完即走的优点,大大降低了用户的使用负担,也使小程序得到了广泛的传播.在阿里巴巴,小程序也被广泛地应 ...

  3. 洛谷3973 TJOI2015线性代数(最小割+思维)

    感觉要做出来这个题,需要一定的线代芝士 首先,我们来观察这个柿子. 我们将\(B\)的权值看作是收益的话,\(C\)的权值就是花费. 根据矩阵乘法的原理,只有当\(a[i]和a[j]\)都为\(1\) ...

  4. Chrome 实时字幕

    Chrome 实时字幕

  5. LCP 07.传递消息

    题目 小朋友 A 在和 ta 的小伙伴们玩传信息游戏,游戏规则如下: 有 n 名玩家,所有玩家编号分别为 0 - n-1,其中小朋友 A 的编号为 0 每个玩家都有固定的若干个可传信息的其他玩家(也可 ...

  6. [CSP-S 2021] 廊桥分配 题解

    写篇题解来纪念我炸掉的CSP 唯一会做的题代码写挂了(痛苦面具 思路 我看到这道题第一眼想到的是线段树,感觉可以用线段树维护飞机入站到出战的这段时间,想了半天想不到代码怎么写. 国内机场与国外机场要分 ...

  7. Verilog设计技巧实例及实现

    Verilog设计技巧实例及实现 1 引言 最近在刷HDLBits的过程中学习了一些Verilog的设计技巧,在这里予以整理.部分操作可能降低代码的可读性和Debug的难度,请大家根据实际情况进行使用 ...

  8. 转载:10G以太网光口与Aurora接口回环实验

    10G以太网光口与高速串行接口的使用越来越普遍,本文拟通过一个简单的回环实验,来说明在常见的接口调试中需要注意的事项.各种Xilinx FPGA接口学习的秘诀:Example Design.欢迎探讨. ...

  9. hdu 3038 How Many Answers Are Wrong(并查集)

    题意: N和M.有N个数. M个回答:ai, bi, si.代表:sum(ai...bi)=si.如果这个回答和之前的冲突,则这个回答是假的. 问:M个回答中有几个是错误的. 思路: 如果知道sum( ...

  10. hdu 2830 Matrix Swapping II(额,,排序?)

    题意: N*M的矩阵,每个格中不是0就是1. 可以任意交换某两列.最后得到一个新矩阵. 问可以得到的最大的子矩形面积是多少(这个子矩形必须全是1). 思路: 先统计,a[i][j]记录从第i行第j列格 ...