CCO 2019 Day2

Luogu P6680

题目描述

给定一张 \(N\) 个点,\(M\) 条边的无向简单图。

如果存在 \(1\le a<b<c\le N\) 满足存在边 \((a,b),(a,c)\),并且不存在 \((b,c)\),则加入边 \((b,c)\)

求最后的边数。

思路

首先我们可以把边看做从小的连向大的。

通过观察可以发现只有在这种情况下才会建边:

image

这里红色的边是新加入的。

如果每次我们都对这样的建一个完全图,那么有很多边会被重复加入,所以我们考虑每个点会伸出去多少条边。

可以发现,这里只需要让最靠前的一个儿子建边就行了,也就是这样:

image

因为在枚举到这个儿子时又会传递给下一个。

所以我们用一个 set 记录连向的结点,然后用启发式合并的方法传递给儿子。

空间复杂度 \(O(N+M)\),时间复杂度 \(O(N\log^2 M)\)

代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;

const int MAXN = 100001;

int n, m;
ll ans;
set<int> e[MAXN];

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n >> m;
  for(int i = 1, u, v; i <= m; ++i) {
    cin >> u >> v;
    e[u].insert(v);
  }
  for(int i = 1; i <= n; ++i) {
    ans += e[i].size();
    if(e[i].size()) {
      int x = *e[i].begin();
      e[i].erase(x);
      if(e[i].size() > e[x].size()) {
        swap(e[i], e[x]);
      }
      for(int v : e[i]) {
        e[x].insert(v);
      }
    }
  }
  cout << ans;
  return 0;
}

Luogu P6681

题目描述

给定 \(N\) 个长度至多为 \(M\)\(01\) 串。你要用两种不同的字符串组合拼接出一个相同的 \(01\) 串,你可以使用重复的字符串。求这个拼接出字符串的最短长度。如果没有输出 \(-1\)

思路

\(dp_S\) 表示更长的字符串比更短的字符串长出的部分为 \(S\) 时的最短长度。

每次我们暴力枚举下一个位置填什么字符串并拼接即可。

空间复杂度 \(O(NM)\),时间复杂度 \(O(NM(NM+\log NM))\)

代码

#include<bits/stdc++.h>
using namespace std;
using ll = long long;

const int MAXN = 51;

struct Node {
  string s;
  int dis;
};

struct cmp {
  bool operator()(const Node &a, const Node &b) const {
    return a.dis > b.dis;
  }
};

int n, m;
map<string, int> dist;
map<string, bool> vis;
string s[MAXN];

bool check(const string &a, const string &b) {
  for(int i = 0; i < min(int(a.size()), int(b.size())); ++i) {
    if(a[i] != b[i]) {
      return 0;
    }
  }
  return 1;
}

string Get(const string &a, const string &b) {
  string ret = "";
  for(int i = 0; i < max(int(a.size()), int(b.size())); ++i) {
    if(i >= int(a.size())) {
      ret += b[i];
    }
    if(i >= int(b.size())) {
      ret += a[i];
    }
  }
  return ret;
}

void dij() {
  priority_queue<Node, vector<Node>, cmp> pq;
  for(int i = 1; i <= n; ++i) {
    for(int j = 1; j <= n; ++j) {
      if(i != j && check(s[i], s[j])) {
        string t = Get(s[i], s[j]);
        int w = max(0, int(s[j].size()) - int(s[i].size()));
        if(!dist.count(t) || int(s[i].size()) + w < dist[t]) {
          dist[t] = int(s[i].size()) + w;
          pq.push({t, int(s[i].size()) + w});
        }
      }
    }
  }
  for(; !pq.empty(); ) {
    auto [str, dis] = pq.top();
    pq.pop();
    if(vis.count(str)) {
      continue;
    }
    vis[str] = 1;
    for(int i = 1; i <= n; ++i) {
      if(check(str, s[i])) {
        string t = Get(str, s[i]);
        int w = max(0, int(s[i].size()) - int(str.size()));
        if(!dist.count(t) || dis + w < dist[t]) {
          dist[t] = dis + w;
          pq.push({t, dis + w});
        }
      }
    }
  }
}

int main() {
  ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  cin >> n >> m;
  for(int i = 1; i <= n; ++i) {
    cin >> s[i];
  }
  dij();
  cout << (!dist.count("") ? -1 : dist[""]);
  return 0;
}
posted @ 2024-09-25 11:22  Yaosicheng124  阅读(14)  评论(0编辑  收藏  举报