Modules(最小树形图)

Modules

题目链接:here

朱刘算法

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 const int inf = 0x3f3f3f3f;
 5 const int maxn = 3010;
 6 const int maxe = 3010 * 2;
 7 struct Edge{
 8     int u, v, w;
 9     Edge(int u = 0, int v = 0, int w = 0) : u(u), v(v), w(w) {}
10 }e[maxe];
11 
12 int  pre[maxn], id[maxn], vis[maxn];
13 LL in[maxn];
14 
15  LL Dir_MST(int n, int m){
16     int rt = 0;
17     LL ans = 0;
18     for(int i = 1; i <= n; i++)  e[m++] = Edge(rt, i, 0);
19     n++;
20     int cnt = m;
21     while(true) {
22         for(int i = 0; i < n; i++) in[i] = -inf;
23         for(int i = 0; i < cnt; i++) {
24             int u = e[i].u, v = e[i].v, w = e[i].w;
25             if(w > in[v] && u != v) {
26                 in[v] = w;
27                 pre[v] = u;
28             }
29         }
30         int cntnode = 0;
31         memset(vis, -1, sizeof(vis));
32         memset(id, -1, sizeof(id));
33         in[rt] = 0;
34         for(int i = 0; i < n; i++){
35             ans = ans + in[i];
36             int v = i;
37             while(vis[v] != i && v != rt && id[v] == -1) {
38                 vis[v] = i;
39                 v = pre[v];
40             }
41             if(id[v] == -1 && v != rt){
42                 for(int u = pre[v]; u != v; u = pre[u]) id[u] = cntnode;
43                 id[v] = cntnode++;
44             }
45         }
46         if(cntnode == 0) break;
47         for(int i = 0; i < n; i++){
48             if(id[i] == -1) id[i] = cntnode++;
49         }
50         for(int i = 0; i < cnt; i++){
51             int v = e[i].v;
52             e[i].u = id[e[i].u];
53             e[i].v = id[e[i].v];
54             if(e[i].u != e[i].v) e[i].w -= in[v];
55         }
56         n = cntnode;
57         rt = id[rt];
58     }
59     return ans;
60 }
61 
62 int main(){
63     int t, n, m;
64     //freopen("in.txt", "r", stdin);
65     scanf("%d", &t);
66     while(t--) {
67         scanf("%d %d", &n, &m);
68         LL ans = 0;
69         int x;
70         for(int i = 0; i < n; i++) {
71             scanf("%d", &x);
72             ans += x;
73         }
74         int u, v, w;
75         for(int i = 0; i < m; i++){
76             scanf("%d %d %d", &u, &v, &w);
77             e[i] = Edge(v, u, w);
78         }
79         printf("%lld\n", Dir_MST(n, m) + ans);
80     }
81     return 0;
82 }
View Code

 

转载于:https://www.cnblogs.com/yijiull/p/7543449.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值