zoukankan      html  css  js  c++  java
  • CodeForces 1487C Minimum Ties(建图、模拟)

    Problem - C - Codeforces

    题目大意:

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

    思路:

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

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

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

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

    接下来我们可以 \(\mathcal O(n^3)\) 的进行模拟删环,记录答案。

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

    Code:
    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;
    }
    
  • 相关阅读:
    9.20 kali中的Metasploit生成木马控制windows 以及http协议相关
    9.19 接上一篇,jss
    9.18 DNS服务安装
    9.17 ubuntu安装LAMP服务
    线程的安全问题
    java实现多线程(上)
    异常处理
    抽象方法和接口、内部类
    面向对象的一些关键字和方法
    Object类和包装类的一些方法
  • 原文地址:https://www.cnblogs.com/Nepenthe8/p/15625911.html
Copyright © 2011-2022 走看看