最小树形图
Posted fighting-sh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小树形图相关的知识,希望对你有一定的参考价值。
最小树形图
题目描述
这是一道模板题。
给定包含 n 个结点, m 条有向边的一个图。试求一棵以结点 r 为根的最小树形图,并输出最小树形图每条边的权值之和,如果没有以 r为根的最小树形图,输出 ?1。
输入格式
第一行包含三个整数 n,m,r,意义同题目所述。
接下来 mm 行,每行包含三个整数 u,v,w表示图中存在一条从 u 指向 v 的权值为 w 的有向边。
输出格式
如果原图中存在以 r 为根的最小树形图,就输出最小树形图每条边的权值之和,否则输出 -1。
样例
样例输入1
4 6 1
1 2 3
1 3 1
4 1 2
4 2 2
3 2 1
3 4 1
样例输出 1
3
样例解释 1
最小树形图中包含第 2, 5, 6 三条边,总权值为 1 + 1 + 1 = 3
样例输入 2
4 6 3
1 2 3
1 3 1
4 1 2
4 2 2
3 2 1
3 4 1
样例输出 2
4
样例输出 2
最小树形图中包含第 3, 5, 6 三条边,总权值为 2 + 1 + 1 =4
样例输入 3
4 6 2
1 2 3
1 3 1
4 1 2
4 2 2
3 2 1
3 4 1
样例输出 3
-1
样例解释 3
无法构成最小树形图,故输出 -1 。
模板题
下标从0开始
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <math.h> 5 const int INF=0x3f3f3f3f; 6 #define MAXN 400005 7 #define MAXM 400010 8 using namespace std; 9 struct Edge{ 10 int u,v; 11 int cost; 12 }edge[MAXM]; 13 14 int pre[MAXN],id[MAXN],visit[MAXN]; 15 int in[MAXN]; 16 17 int zhuliu(int root,int n,int m){ 18 int res=0; 19 while(1){ 20 for(int i=0;i<n;i++){ 21 in[i]=INF; 22 } 23 for(int i=0;i<m;i++){ 24 if(edge[i].u!=edge[i].v&&edge[i].cost<in[edge[i].v]){ 25 pre[edge[i].v]=edge[i].u; 26 in[edge[i].v]=edge[i].cost; 27 } 28 } 29 for(int i=0;i<n;i++){ 30 if(i!=root && in[i]==INF){ 31 return -1; 32 } 33 } 34 int tn=0; 35 memset(id,-1,sizeof(id)); 36 memset(visit,-1,sizeof(visit)); 37 in[root]=0; 38 for(int i=0;i<n;i++){ 39 res+=in[i]; 40 int v=i; 41 while(visit[v]!=i&&id[v]==-1&&v!=root){ 42 visit[v]=i; 43 v=pre[v]; 44 } 45 if(v!=root&&id[v]==-1){ 46 for(int u=pre[v];u!=v;u=pre[u]){ 47 id[u]=tn; 48 } 49 id[v]=tn++; 50 } 51 } 52 if(tn==0) break; 53 for(int i=0;i<n;i++){ 54 if(id[i]==-1){ 55 id[i]=tn++; 56 } 57 } 58 for(int i=0;i<m;){ 59 int v=edge[i].v; 60 edge[i].u=id[edge[i].u]; 61 edge[i].v=id[edge[i].v]; 62 if(edge[i].u != edge[i].v){ 63 edge[i++].cost-=in[v]; 64 } 65 else{ 66 swap(edge[i],edge[--m]); 67 } 68 } 69 n=tn; 70 root=id[root]; 71 } 72 return res; 73 } 74 75 76 int main(){ 77 std::ios::sync_with_stdio(false); 78 int n,m,r; 79 cin>>n>>m>>r; 80 for(int i=0;i<m;i++){ 81 cin>>edge[i].u>>edge[i].v>>edge[i].cost; 82 edge[i].u--; 83 edge[i].v--; 84 } 85 int ans=zhuliu(r-1,n,m); 86 cout<<ans<<endl; 87 }
下标从1开始(要改两个地方:1.tn 2.--m -> m--)
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <math.h> 5 const int INF=0x3f3f3f3f; 6 #define MAXN 400005 7 #define MAXM 400010 8 using namespace std; 9 struct Edge{ 10 int u,v; 11 int cost; 12 }edge[MAXM]; 13 14 int pre[MAXN],id[MAXN],visit[MAXN]; 15 int in[MAXN]; 16 17 int zhuliu(int root,int n,int m){ 18 int res=0; 19 while(1){ 20 for(int i=1;i<=n;i++){ 21 in[i]=INF; 22 } 23 for(int i=1;i<=m;i++){ 24 if(edge[i].u!=edge[i].v&&edge[i].cost<in[edge[i].v]){ 25 pre[edge[i].v]=edge[i].u; 26 in[edge[i].v]=edge[i].cost; 27 } 28 } 29 for(int i=1;i<=n;i++){ 30 if(i!=root && in[i]==INF){ 31 return -1; 32 } 33 } 34 int tn=1; 35 memset(id,-1,sizeof(id)); 36 memset(visit,-1,sizeof(visit)); 37 in[root]=0; 38 for(int i=1;i<=n;i++){ 39 res+=in[i]; 40 int v=i; 41 while(visit[v]!=i&&id[v]==-1&&v!=root){ 42 visit[v]=i; 43 v=pre[v]; 44 } 45 if(v!=root&&id[v]==-1){ 46 for(int u=pre[v];u!=v;u=pre[u]){ 47 id[u]=tn; 48 } 49 id[v]=tn++; 50 } 51 } 52 if(tn==1) break; 53 for(int i=1;i<=n;i++){ 54 if(id[i]==-1){ 55 id[i]=tn++; 56 } 57 } 58 for(int i=1;i<=m;){ 59 int v=edge[i].v; 60 edge[i].u=id[edge[i].u]; 61 edge[i].v=id[edge[i].v]; 62 if(edge[i].u != edge[i].v){ 63 edge[i++].cost-=in[v]; 64 } 65 else{ 66 swap(edge[i],edge[m--]); 67 } 68 } 69 n=tn-1; 70 root=id[root]; 71 } 72 return res; 73 } 74 75 76 int main(){ 77 std::ios::sync_with_stdio(false); 78 int n,m,r; 79 cin>>n>>m>>r; 80 for(int i=1;i<=m;i++){ 81 cin>>edge[i].u>>edge[i].v>>edge[i].cost; 82 } 83 int ans=zhuliu(r,n,m); 84 cout<<ans<<endl; 85 }
以上是关于最小树形图的主要内容,如果未能解决你的问题,请参考以下文章