最小树形图

最小树形图

https://loj.ac/problem/140

题目描述

这是一道模板题。

给定包含 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 }
View Code

下标从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 }
View Code
原文地址:https://www.cnblogs.com/Fighting-sh/p/9994314.html