[AtCoder ARC098] Donation| 建图 | 树型dp

简介: 有n个点m条边,每一个点有两个属性,在这个点上的时候要至少有A元,然后要在这个点上支付B元,可以选择在任意时候支付求最少要携带多少元,才能够将所有的点都支付一遍

Donation


18b9fbb5eea343bdb11f7f21cefec42c.png4f0700f4a1cf492081c73e6ed0de97cb.png


input1:


4 5
3 1
1 2
4 1
6 2
1 2
2 3
2 4
1 4
3 4


067a88c82fd74743916217b6c48cedab.png


input2:


5 8
6 4
15 13
15 19
15 1
20 7
1 3
1 4
1 5
2 3
2 4
2 5
3 5
4 5


output2:


44


input3:


9 10
131 2
98 79
242 32
231 38
382 82
224 22
140 88
209 70
164 64
6 8
1 6
1 4
1 3
4 7
4 9
3 7
3 9
5 9
2 5


output3:


582


有n个点m条边,每一个点有两个属性,在这个点上的时候要至少有A元,然后要在这个点上支付B元,可以选择在任意时候支付

求最少要携带多少元,才能够将所有的点都支付一遍


int head[maxn];
int n,m,cnt,tot;
ll a[maxn],b[maxn],c[maxn],id[maxn];
int fa[maxn];
int lson[maxn],rson[maxn];
struct node{
  int v,nex;
}e[maxn];
void addEdge(int u,int v){
  e[cnt].v = v;
  e[cnt].nex = head[u];
  head[u] = cnt ++;
}
void init(){
  for(int i=0;i<maxn;i++) fa[i] = i,head[i] = -1;
  cnt = 0;
  tot = 0;
}
bool cmp(int x,int y){
  return a[x] < a[y];
}
int find(int x){
  if(x == fa[x]) return x;
  else return fa[x] = find(fa[x]);
}
void add(int u,int v){
  int fau = find(u);
  int fav = find(v);
  if(fau == fav) return ;
  tot ++;
  u = fau;
  v = fav;
  lson[tot] = u;
  rson[tot] = v;
  a[tot] = max(a[u],a[v]);
  b[tot] = b[u] + b[v];///cost cal
  fa[u] = tot;
  fa[v] = tot;
  fa[tot] = tot;
}
ll dp[maxn];
void dfs(int u){
  if(lson[u]){
    dfs(lson[u]);
    dfs(rson[u]);
  }else dp[u] = a[u];
  dp[u] = min(
  max(a[u]-b[lson[u]],dp[lson[u]]),
  max(a[u]-b[rson[u]],dp[rson[u]])
  );
}
int main()
{
  init();
  n = read,m = read;
  for(int i=1;i<=n;i++) a[i] = read,b[i] = read;
  for(int i=1;i<=n;i++) a[i] = max(a[i] - b[i], 0LL),id[i] = i;
  sort(id+1,id+1+n,cmp);
  for(int i=1;i<=m;i++){
    int u = read,v = read;
    addEdge(u,v);
    addEdge(v,u);
  }
  /*for(int i=1;i<=n;i++){
    cout<<id[i]<<' ';
  }
  puts("");*/
  tot = n;
  // puts("ok");
  for(int i=1;i<=n;i++){
    int u = id[i];
    for(int j = head[u]; ~j; j = e[j].nex){
      int to = e[j].v;
      if(a[to] <= a[u]) add(u,to);
    }
  }
  dfs(tot);
  cout << dp[tot] + b[tot] <<endl;
    return 0;
}


文章知识点与官方知识档案匹配,可进一步学习相关知识

算法技能树leetcode-动态规划22-括号生成7992 人正在系统学习中






目录
相关文章
AtCoder Beginner Contest 223 D - Restricted Permutation(建图 思维 构造 拓扑排序)
AtCoder Beginner Contest 223 D - Restricted Permutation(建图 思维 构造 拓扑排序)
132 0
|
机器学习/深度学习
AtCoder Beginner Contest 218 F - Blocked Roads (最短路径还原 思维)
AtCoder Beginner Contest 218 F - Blocked Roads (最短路径还原 思维)
99 0
AtCoder Beginner Contest 216 D - Pair of Balls (思维建图 拓扑排序判断有向图是否有环)
AtCoder Beginner Contest 216 D - Pair of Balls (思维建图 拓扑排序判断有向图是否有环)
125 0
AtCoder Beginner Contest 221 D - Online games(差分 离散化 区间)
AtCoder Beginner Contest 221 D - Online games(差分 离散化 区间)
134 0
AtCoder Beginner Contest 203(Sponsored by Panasonic) D.Pond(二分+二维前缀和)
AtCoder Beginner Contest 203(Sponsored by Panasonic) D.Pond(二分+二维前缀和)
90 0
AtCoder Beginner Contest 226 E - Just one(dfs求连通块 组合数学)
AtCoder Beginner Contest 226 E - Just one(dfs求连通块 组合数学)
105 0
AtCoder Beginner Contest 216 G - 01Sequence (并查集 贪心 树状数组 差分约束)
AtCoder Beginner Contest 216 G - 01Sequence (并查集 贪心 树状数组 差分约束)
152 0
AtCoder Beginner Contest 221 E - LEQ(组合数学 树状数组)
AtCoder Beginner Contest 221 E - LEQ(组合数学 树状数组)
153 0
|
人工智能 BI
[Atcoder ARC124] XOR Matching 2-小思维 | 暴力
题意: 给出n,两个数列a[1] -> a[n],b[1] -> b[n] 问有多少个x,可以使得在我们任意一种方式排列b[]之后,有a[i] ^ b[i] == x (1 <= i <= n) 思路: 首先我们可以确定所有的答案一定在a[1] ^ b[i] (1 <= i <= n)之内,所以我们只需要将这些个x的解空间单独放到数组c[]里,然后遍历x的解空间c[],将c[i] ^ a[i]的结果记录在d[]里面,然后判断b[],d[]是否完全相同即可,如果完全相同,就可以记录答案,注意最终答案要进行去重
116 0
[Atcoder ARC124] XOR Matching 2-小思维 | 暴力