Acwing第72场周赛题解

64 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情
本文已参与「新人创作礼」活动,一 起开启掘金创作之路。
## AcWing 4624. 最小值

image.png
题目很简单只要min{a,b,(a + b)/3}输出即可
## AcWing 4625. 压缩文件

image.png 解法

因为每个ai文件压缩过后会变成bi所以(biai)(bi - ai) 的差值就是执行这个文件压缩操作的收益为了让收益最大并且次数最小所以我们对(biai)(bi - ai) 的差值进行排序遍历即可 Code

int a[N];
void solve()
{
   int n,m; cin >> n >> m;
   int num = 0;
   rep(i,n){
       int x,y; cin >> x >> y;
       num += x;
       a[i] = x- y;
   }
   sort(a + 1,a + 1 + n,[](int a,int b){
       return a > b;
   });
   bool f = false;
   int cnt = 0;
   if(num <= m) {
       cout << 0 << endl;
       return;
   }
   rep(i,n) {
        num -= a[i];
       cnt ++;
       if(num <= m) {
           f = 1;
           break;
       }
   }
   if(f) cout << cnt << endl;
   else cout << -1 << endl;
}

## AcWing 4626. 最小移动距离

image.png 解法

我们可以想到如果xyxy互为目标点的话就代表他们之间形成了一个环所以这题我们就根据环来写我们发现如果环内的数量是奇数的话那么它的最小移动距离肯定是这个环的本身长度(因为无法两两对应只能回到本身)所以偶数长度环的最小移动距离是环长度的二分之一
对于在图中求环这个方法如果你学过Tarjan缩点的话是很容易想到这个方法的因为缩点过后我们都会把这个环看成一个点并且这个点和其它点是相互独立的所以我们只需要对比缩点过后入度为0的点数量是否和缩点过后的点数量相等就可以知道是否每个点都在一个环内

Code

int dfn[N],low[N],num,co[N],col;
int top,st[N];
int si[N];
int de[N];
vector<int> v[N];
void Tarjan(int u)///tarjan缩点
{
    dfn[u] = low[u] = ++ num;
    st[++top] = u;
    for(auto x : v[u])
    {
       if(!dfn[x]) { // 深度优先
        Tarjan(x);
        low[u] = min(low[u],low[x]);
       }else if(!co[x]) low[u] = min(low[u],dfn[x]);
       // 判断是否再栈中
    }
    if(low[u] == dfn[u]) { // 退栈
        co[u] = ++col; // 记录在第几个集合
        ++ si[col];//记录集合数量
        while(st[top] != u) {
            ++ si[col];
            co[st[top]] = col;
            top --;
        }
        top --;
    }
}
int lcm(int a,int b) {
  return a * b / __gcd(a,b);  
};
void solve()
{
   int n; cin >> n;
   rep(i,n) {
       int x; cin >> x;
       v[i].pb(x);
   }
   rep(i,n) if(!dfn[i]) Tarjan(i);//缩点
   rep(i,n) for(auto x : v[i])
   if(co[i] != co[x]) de[co[x]] ++;//统计入度
   int res = 0;
   int idx = 0;
   rep(i,col) if(!de[i])  idx ++;//记录入度为0
   cout << idx << endl;
   cout << col << endl;
   if(idx != col) {
       cout << -1 << endl;
       return;
   }
   if(si[1] & 1) res = si[1];
   else res = si[1]/2;
   for(int i = 2; i <= col; i++) {
       res = lcm(res,(si[i] & 1 ? si[i] : si[i]/2 ));
   }
   cout << res << endl;
}