• Codeforces Round #599 (Div. 2) E. Sum Balance


    这题写起来真的有点麻烦,按照官方题解的写法
    先建图,然后求强连通分量,然后判断掉不符合条件的换
    最后做dp转移即可
    虽然看起来复杂度很高,但是n只有15,所以问题不大

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <bitset>
    #include <algorithm>
    #include <iomanip>
    #include <cmath>
    #include <ctime>
    #include <functional>
    #include <unordered_set>
    #include <unordered_map>
    #include <queue>
    #include <deque>
    #include <stack>
    #include <complex>
    #include <cassert>
    #include <random>
    #include <cstring>
    #include <numeric>
    #define ll long long
    #define ld long double
    #define null NULL
    #define all(a) a.begin(), a.end()
    #define forn(i, n) for (int i = 0; i < n; ++i)
    #define sz(a) (int)a.size()
    #define lson l , m , rt << 1
    #define rson m + 1 , r , rt << 1 | 1
    #define bitCount(a)  __builtin_popcount(a)
    template<class T> int gmax(T &a, T b) { if (b > a) { a = b; return 1; } return 0; }
    template<class T> int gmin(T &a, T b) { if (b < a) { a = b; return 1; } return 0; }
    using namespace std;
    string to_string(string s) { return '"' + s + '"'; }
    string to_string(const char* s) { return to_string((string) s); }
    string to_string(bool b) { return (b ? "true" : "false"); }
    template <typename A, typename B>
    string to_string(pair<A, B> p) { return "(" + to_string(p.first) + ", " + to_string(p.second) + ")"; }
    template <typename A>
    string to_string(A v) { bool first = true; string res = "{"; for (const auto &x : v) { if (!first) { res += ", "; } first = false; res += to_string(x); } res += "}"; return res; }
    void debug_out() { cerr << endl; }
    template <typename Head, typename... Tail>
    void debug_out(Head H, Tail... T) { cerr << " " << to_string(H); debug_out(T...); }
    #ifdef LOCAL
    #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
    #else
    #define debug(...) 42
    #endif
    
    const int MAXN = 75005;
    vector<int> graph[MAXN];
    vector<int> group[MAXN];
    int dfn[MAXN], low[MAXN];
    int dcnt;
    int col[MAXN + 5], ccnt;
    bool vis[MAXN + 5];
    int stk[MAXN + 5], tp;
    vector<pair<int, int>> dp[32768];
    
    void Tarjan_scc(int u) {
    	dfn[u] = ++dcnt, low[u] = dcnt, vis[u] = true;
    	stk[++tp] = u;
    	for(int i = 0; i < (int)graph[u].size(); i++) {
    		int v = graph[u][i];
    		if(!dfn[v]) {
    			Tarjan_scc(v);
    			low[u] = min(low[u], low[v]);
    		} else if(vis[v]) low[u] = min(low[u], low[v]);
    	}
    	if(dfn[u] == low[u]) {
    		++ccnt;
    		while(true) {
    			col[stk[tp]] = ccnt;
    			vis[stk[tp]] = false;
    			if(stk[tp--] == u)
    				break;
    		}
    	}
    }
    
    
    int main() {
        int k;
        while(~scanf("%d", &k)) {
            tp = -1; ccnt = 0; dcnt = 0;
            for(int i = 0; i < MAXN; ++i) {
                dfn[i] = 0;
                graph[i].clear();
                group[i].clear();
            }
    
            vector<ll> sum;
            vector<pair<int, int> > vc;
            map<ll, pair<int, int> > mp;
    
            int tot = 0;
            ll allSum = 0;
            for(int i = 0; i < k; ++i) {
                int x; scanf("%d", &x);
                ll tmpSum = 0;
                for(int j = 0; j < x; ++j) {
                    int y; scanf("%d", &y);
                    vc.push_back(make_pair(y, i));
                    mp[y] = make_pair(tot, i);
                    tot ++;
                    tmpSum += y;
                }
                sum.push_back(tmpSum);
                allSum += tmpSum;
            }
            // debug(allSum);
    
            if(allSum % k) {
                printf("No
    ");
                continue;
            } 
    
            allSum /= k;
            set<int> selfCircle;
            set<pair<int, int>> hasEdge;
    
            // debug(allSum);
            for(int i = 0, len = vc.size(); i < len; ++i) {
                ll searchNum = allSum - sum[vc[i].second] + vc[i].first;
                if(mp.find(searchNum) == mp.end()) continue;
                else if( mp[searchNum].second == vc[i].second && mp[searchNum].first != i) {
                    // solve specfial condition
                    continue;
                } else if(mp[searchNum].first == i) {
                    // debug(i);
                    selfCircle.insert(i);
                }
    
                graph[i].push_back(mp[searchNum].first);
                hasEdge.insert(make_pair(i, mp[searchNum].first));
    
                debug(i, mp[searchNum].first);
            }
    
           
            for(int i = 0; i < tot; ++i) {
                if(!dfn[i]) Tarjan_scc(i);
            } 
    
            for(int i = 0; i < tot; ++i) {
                // printf("%d ", col[i]);
                group[col[i]].push_back(i);
            }
            // printf("
    ");
    
            for(int i = 1; i <= ccnt; ++i) {
                // debug(i, group[i].size());
                if(group[i].size() == 1 && selfCircle.count(group[i][0])) {
                    int id = group[i][0];
                    vector<pair<int, int> > tmpPair;
                    tmpPair.push_back(make_pair(vc[id].first, vc[id].second + 1));
                    dp[1<<vc[id].second] = tmpPair;
                    // debug(dp[1<<vc[id].second]);
                }
                else if(group[i].size() > 1) {
                    vector<pair<int, int> > tmpPair;
                    int tmp = 0;
                    int len = group[i].size();
                    bool suc = true;
                    for(int j = 0; j < len; ++j) {
                        int to = group[i][j];
                        if(tmp & (1<<vc[to].second)) { suc = false; break; }
                        tmp |= 1<<vc[to].second;
                    }
                    if(suc == false) {
                        continue;
                    }
                    
                    for(int j = 0; j < len; ++j) {
                        for(int k = 0; k < len; ++k) {
                            int fr = group[i][j]; int to = group[i][k];
                            if(hasEdge.count(make_pair(fr, to))) {
                                tmpPair.push_back(make_pair(vc[to].first, vc[fr].second + 1));
                            }
                        }
                    }
    
                    dp[tmp] = tmpPair;
                    // debug(dp[tmp], tmp);
                }
            }
    
            for(int i = 0; i < (1<<k); ++i) {
                for (int s=(i-1)&i; s; s=(s-1)&i) {
                    int t = i ^ s;
                    if(dp[s].size() > 0 && dp[t].size() > 0) {
                        dp[i] = dp[s];
                        dp[i].insert(dp[i].end(), dp[t].begin(), dp[t].end());
                        break;
                    }
                }
            }
    
            auto cmp = [&](pair<int, int> &A, pair<int, int> &B) {
                return mp[A.first].second < mp[B.first].second;
            };
    
            int end = (1<<k) - 1;
            if(dp[end].size() > 0 ) {
                printf("Yes
    ");
                // debug(dp[end]);
                sort(dp[end].begin(), dp[end].end(), cmp);
                for(int i = 0; i < k; ++i) {
                    printf("%d %d
    ", dp[end][i].first,  dp[end][i].second);
                }
            } else printf("No
    ");
            
        }
        return 0;
    }
    
  • 相关阅读:
    R语言 实验三 数据探索和预处理
    Java学习——包及可见性
    Java学习——包及可见性
    Java学习——使用Static修饰符
    Java学习——使用Static修饰符
    CSDN也有我的博客啦
    将博客搬至CSDN
    Java学习——方法中传递参数分简单类型与复杂类型(引用类型)编程计算100+98+96+。。。+4+2+1的值,用递归方法实现
    Java学习——方法中传递参数分简单类型与复杂类型(引用类型)编程计算100+98+96+。。。+4+2+1的值,用递归方法实现...
    Java学习——方法中传递参数分简单类型与复杂类型(引用类型)
  • 原文地址:https://www.cnblogs.com/Basasuya/p/11847537.html
Copyright © 2020-2023  润新知