[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 ...
随机推荐
- Parcel Fabric Tools(宗地结构工具)
宗地结构工具 1.图层和表视图 # Process: 创建宗地结构图层 arcpy.MakeParcelFabricLayer_fabric("", 输出图层) # Process ...
- 洛谷4360[CEOI2004]锯木厂选址 (斜率优化+dp)
qwq 我感觉这都已经不算是斜率优化\(dp\)了,感觉更像是qwq一个\(下凸壳优化\)转移递推式子. qwq 首先我们先定义几个数组 \(sw[i]\)表示\(w[i]\)的前缀和 \(val[i ...
- jenkins+allure中测试包括为空,没有数据
- Endian
Endian 寻址 多字节对象被存储为连续的字节序列,对象的地址为所使用字节中最小的地址. 例如,假设一个类型为 int 的变量 a 的地址为 0x100,也就是说,地址表达式 &a 的值为 ...
- VS2019中安装2017,2015
VS2019中安装2017,2015
- HCNP Routing&Switching之BGP路由宣告
前文我们了解了BGP报文结构.类型以及邻居状态相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15422924.html:今天我们来聊一聊BGP路由宣告 ...
- Convolutional Neural Network-week1编程题(TensorFlow实现手势数字识别)
1. TensorFlow model import math import numpy as np import h5py import matplotlib.pyplot as plt impor ...
- DDL_Killer Alpha版本 Bug集中反馈处
本博客用于DDL_Killer Alpha版本的Bug集中反馈. 您可以在本博客的下方评论区处留言,反馈您在使用DDl_Killer的过程中遇到的问题,以帮助我们更好的改进本产品. 我们会尽快修复找到 ...
- Django(71)图片处理器django-imagekit
介绍 ImageKit是用于处理图像的Django应用程序.如果需要从原图上生成一个长宽为50x50的图像,则需要ImageKit. ImageKit附带了一系列图像处理器,用于调整大小和裁剪等常见任 ...
- 碰撞的蚂蚁 牛客网 程序员面试金典 C++ Java Python
碰撞的蚂蚁 牛客网 程序员面试金典 C++ Java Python 题目描述 在n个顶点的多边形上有n只蚂蚁,这些蚂蚁同时开始沿着多边形的边爬行,请求出这些蚂蚁相撞的概率.(这里的相撞是指存在任意两只 ...