ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #599 E - Sum Balance

2019-12-22 23:56:23  阅读:241  来源: 互联网

标签:tarjan include 599 Sum int num low Balance ll


tarjan缩点,枚举子集。
首先avg即平均值是可以直接求出来的,我们假设第i个盒子给出去a,那么平衡需要的是,avg-sumi+a,我们把所有数字开一个map保存下来,如果有该数字,连一条有向边,从a到avg-sumi+a。
可以看到,因为题目说了unique ,所以一个点的出度是固定的,即1。现在要求所有盒子平衡,且每个盒子必须拿出来一个值。那么我们从a连出了一条有向边,如果这是一个可行解的话,那么a会处在一个环中,即a肯定也会被需要,而且还处在当前这条链中。因出度为1,环是简单环,是一条单链。
我们就能够用tarjan缩点,把这个环求出来。
一个可行解是有多个环组成的(不可能一个环,一个环的话就是x->y->z->x,那么其实可以看到x=y=z,那么数字重复了),我们通过状压和枚举子集的方式,来看最后是否能做到。
wa点:wa了很多次,没有判断这种情况,比如一个盒子中80,1,10,平均值为100,那么1会连边10,即连接自己盒子里面的数字,这里在tarjan所点的时候需要特判。同样可能会有多个可行解,对于每一个盒子来说,我们取一个就行。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
    char ch = getchar(); ll x = 0, f = 1;
    while (ch<'0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); }
    return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 5005;
ll a[20*N];
stack<int>st;
ll k,n;
int cap[20 * N], low[20 * N], dfn[20 * N];
ll sum_bx[20];
map<ll, int>mp;
struct node {
    int to, next;
}edge[40*N];
int head[40 * N];
int cnt = 0;
void addedge(int u, int v)
{
    edge[cnt].to = v;
    edge[cnt].next = head[u];
    head[u] = cnt++;
}
vector<int> dp[(1 << 15)];
int tot, tar_tot;
int vis[20 * N];
struct scc_ {
    vector<int>vec;
    int id,sta;
}scc[20*N];
void tarjan(int u)
{
    low[u] = dfn[u] = ++tot;
    st.push(u);
    vis[u] = 1;
    for (int i = head[u]; ~i; i = edge[i].next)
    {
        int v = edge[i].to;
        if (!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(vis[v])
        {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if (dfn[u] == low[u])
    {
        int cur = -1;
        bool flag = 0;
        do
        {
            cur = st.top(); st.pop();
            scc[tar_tot].vec.push_back(cur);
            if(scc[tar_tot].sta&(1 << (cap[cur] - 1)))flag=1;
            scc[tar_tot].sta |= (1 << (cap[cur]-1));
            vis[cur] = 0;
        } while (cur != u);
        if (flag||head[u] == -1 || scc[tar_tot].vec.size() == 1 && edge[head[u]].to != u) {
            tar_tot++;
            return;
        }
        if(dp[scc[tar_tot].sta].empty())dp[scc[tar_tot].sta].push_back(tar_tot);
        tar_tot++;
    }
}
struct ans {
    int box1;
    ll val;
    int  box2;
    ans(int b1, ll v, int b2)
    {
        box1 = b1; val = v; box2 = b2;
    }
    bool operator<(const ans &b)const {
        return box1 < b.box1;
    }
};
vector<ans>as;
int main()
{
    k = read();
    int num = 0;
    ll sum = 0;
    memset(head, -1, sizeof(head));
    upd(i, 1, k)
    {
        n = read();
        up(j, 0, n)
        {
            a[++num] = read();
            cap[num] = i;
            mp[a[num]] = num;
            sum += a[num];
            sum_bx[i] += a[num];
        }
    }
    if (sum%k) { printf("No\n"); return 0; }
    ll avg = sum / k;
    upd(i, 1, num)
    {
        ll temp = avg - sum_bx[cap[i]] + a[i];
        if (mp[temp])
        {
            addedge(i, mp[temp]);
        }
    }
    upd(i, 1, num)
    {
        if (!dfn[i])tarjan(i);
    }
    //cout << dp[8].size() << " " << dp[7].size();
    int S = (1 << k)-1;
    upd(i, 1, S)
    {
        for (int j = i&(i-1); j; j = (j-1)&i)
        {
            if (!dp[j].empty() && !dp[i^j].empty())
            {
                dp[i] = dp[i^j];
                for (auto k : dp[j])
                {
                    dp[i].push_back(k);
                }
                break;
            }
        }
    }
    if (dp[S].size() == 0) {
        printf("No\n"); return 0;
    }
    else
    {
        printf("Yes\n"); 
        for (auto k : dp[S])
        {
            for (int i = 0; i < scc[k].vec.size() - 1; i++)
            {
                ans temp(cap[scc[k].vec[i]], a[scc[k].vec[i]], cap[scc[k].vec[i + 1]]);
                as.push_back(temp);
                //printf("%d\n", as.back().box2);
            }
            as.push_back(ans( cap[scc[k].vec.back()],a[scc[k].vec.back()],cap[scc[k].vec[0]]));
 
        //  printf("%d %d %d\n", as.back().box1, as.back().val, as.back().box2);
        }
        sort(as.begin(), as.end());
        for (auto k : as) {
            printf("%lld %d\n", k.val,k.box2);
        }
    }
    return 0;
}

标签:tarjan,include,599,Sum,int,num,low,Balance,ll
来源: https://www.cnblogs.com/LORDXX/p/12081716.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有