北方大学多校联合训练第十一场E:Modules

北方大学多校联合训练第十一场E:Modules

题目链接:http://112.74.33.53/contest/10/problem/58/

题目大意:有$1$块主板和$n$个增强模块,增强模块可以加在主板或者其他连在主板上的模块上为其带来$p[i]$的增益,当模块$a[i]$连在模块$b[i]$上时,可以带来额外$q[i]$的增益,问最大增益是多少.

最小树形图

不考虑额外增益的情况下,将模块连到模块上的效果与直接连到主板上是一致的,故只需从主板向各个模块连边;考虑额外增益,只需从$b[i]$向$a[i]$额外建边.

代码如下:

 1 #include <cstdio>
 2 #include <cstring>
 3 #define MAXN 3005
 4 #define MAXM 6005
 5 using namespace std;
 6 typedef long long ll;
 7 const ll inf=1000000000000000;
 8 ll T,n,m,p[MAXN],a,b,q;
 9 struct ZL{
10     ll n,m;
11     ll pre[MAXN],id[MAXN],vis[MAXN];
12     ll inEdge[MAXN];
13     struct Edge{
14         ll u,v;
15         ll w;
16     }edge[MAXM];
17     void init(ll n_){
18         n=n_;m=0;
19     }
20     void addedge(ll u,ll v,ll w){
21         edge[m].u=u;
22         edge[m].v=v;
23         edge[m].w=w;
24         m++;
25     }
26     ll Directed_MST(ll root){
27         ll ans=0,u,v;
28         while(1){
29             for(ll i=0;i<n;++i)
30                 inEdge[i]=inf;
31             for(ll i=0;i<m;++i){
32                 u=edge[i].u;
33                 v=edge[i].v;
34                 if(edge[i].w<inEdge[v]&&u!=v) {
35                     pre[v]=u;
36                     inEdge[v]=edge[i].w;
37                 }
38             }
39             for(ll i=0;i<n;++i)
40                 if(i!=root&&inEdge[i]==inf)
41                     return -1;
42             ll cnt=0;
43             memset(id,-1,sizeof(id));
44             memset(vis,-1,sizeof(vis));
45             inEdge[root]=0;
46             for(ll i=0;i<n;++i) {
47                 ans+=inEdge[i];
48                 ll cur=i;
49                 while(vis[cur]!=i&&cur!=root&&id[cur]==-1) {
50                     vis[cur]=i;
51                     cur=pre[cur];
52                 }
53                 if(cur!=root&&id[cur]==-1) {
54                     v=pre[cur];
55                     while(v!=cur) {
56                         id[v]=cnt;
57                         v=pre[v];
58                     }
59                     id[cur]=cnt++;
60                 }
61             }
62             if(cnt==0)return ans;
63             for(int i=0;i<n;++i)
64                 if(id[i]==-1)
65                     id[i]=cnt++;
66             for(int i=0;i<m;++i) {
67                 u=edge[i].u;
68                 v=edge[i].v;
69                 edge[i].u=id[u];
70                 edge[i].v=id[v];
71                 if(id[u]!=id[v])
72                     edge[i].w-=inEdge[v];
73             }
74             n=cnt;
75             root=id[root];
76         }
77         return ans;
78     }
79 }gao;
80 int main(void){
81     scanf("%lld",&T);
82     while(T--){
83         scanf("%lld%lld",&n,&m);
84         gao.init(n+1);
85         for(int i=1;i<=n;++i){
86             scanf("%lld",&p[i]);
87             gao.addedge(0,i,-p[i]);
88         }
89         for(int i=0;i<m;++i){
90             scanf("%lld%lld%lld",&a,&b,&q);
91             gao.addedge(b,a,-q-p[a]);
92         }
93         printf("%lld
",-gao.Directed_MST(0));
94     }
95 }
原文地址:https://www.cnblogs.com/barrier/p/6853313.html