CodeForces - 1487C Minimum Ties(建图、模拟)

Problem - C - Codeforces

题目大意:

给定一个完全图,每个队伍就是一个点,每场比赛就是一条无向边。现在每次可以消掉一个环,使得剩下的边最少。

思路:

有这样一个结论,将一个完全图分成若干个环逐个消去,所有节点出现在所有环上的总次数都相同。

举个例子,比如六阶完全图,可以拆成(0-index):

Copy
0 1 2 3 4 5 0 2 4 1 3 5

三个环,每个节点都总共出现了两次。

接下来我们可以 O(n3) 的进行模拟删环,记录答案。

枚举起点和步长,再 check 是否能构成环,如能构成则标记。

Code:
Copy
int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int T; cin >> T; while (T--) { int n; cin >> n; vector<vector<int>> ans(n, vector<int>(n)); //胜负关系,即答案 vector<vector<int>> ck(n, vector<int>(n)); //边被占用为1 for (int st = 0; st < n; st++) { for (int len = 1; len < n; len++) { vector<bool> vis(n); //点的访问情况 int now = st; bool ok = true; while (!vis[now]) { vis[now] = true; int nxt = (now + len) % n; if (!ans[now][nxt] && !ans[nxt][now] && !ck[now][nxt] && !ck[nxt][now]) { ck[now][nxt] = ck[nxt][now] = 1; now = nxt; } else { ok = false; break; } } fill(vis.begin(), vis.end(), false); now = st; while (!vis[now]) { //线性删除边占用标记,不然会超时 vis[now] = true; int nxt = (now + len) % n; ck[now][nxt] = ck[nxt][now] = 0; } if (!ok) { continue; } now = st; fill(vis.begin(), vis.end(), false); while (!vis[now]) { // cerr << now << " "; vis[now] = true; int nxt = (now + len) % n; ans[now][nxt] = 1; ans[nxt][now] = -1; now = nxt; } // cout << endl; } } // cout << "####" << endl; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { cout << ans[i][j] << " \n"[j == n - 1 && i == n - 2]; } } } return 0; }
posted @   Nepenthe8  阅读(63)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示