Codeforces Round #311 (Div. 2) C(技巧) *D(二分图染色)

原创 2015年07月09日 16:56:15

C. Arthur and Table

http://codeforces.com/contest/557/problem/C


题意:一张桌子有n条桌腿,每条桌腿有相应的长度和移动花费值,要使桌子平稳,最长桌腿的数量M 与桌腿的数量关系为 M*2>N,求出使桌子平稳的最小花费值。

思路:将桌腿按照长度由大到小排序,依次以不同长度的桌腿cnt 作为桌子的平稳支撑,保留另外cnt-1条花费值大的桌腿,则可得到移动的桌腿的最小花费值。具体的做法是使用数组将所有的花费值个数存起来,遍历花费值200~1,求得cnt-1 条花费大的桌腿。

AC.

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;
const int INF = 0x3f3f3f;
const int maxn = 1e5 + 5;
struct node {
    int len, d;
    bool operator < (const node & A) const {
        return len > A.len;
    }
}leg[maxn];
int num[205];

bool cmp(node x, node y) {
    return x.d < y.d;
}
int main()
{
    //freopen("in", "r", stdin);
    int n;
    while(~scanf("%d", &n)) {
        memset(num, 0, sizeof(num));

        for(int i = 1; i <= n; ++i) {
            scanf("%d", &leg[i].len);
        }
        int sum = 0;
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &leg[i].d);
            num[leg[i].d] ++;
            sum += leg[i].d;
        }
        sort(leg+1, leg + n+1);

        int res = 0, ans = 0, cnt = 0;

        for(int i = 1; i <= n+1; ++i) {
            if(i == 1 || leg[i].len == leg[i-1].len) {
                res += leg[i].d;
                num[leg[i].d]--;
                cnt++;
            }
            else {
                for(int j = 200;  j >= 1; --j) {
                    if(num[j] > 0) {
                        if(num[j] <= cnt-1) {
                            res += num[j]*j;
                            cnt -= num[j];
                        }
                        else  {
                            res += (cnt-1)*j;
                            cnt = 1;
                        }
                    }
                    if(cnt <= 1) break;
                }
                ans = max(ans, res);
                res = leg[i].d;
                cnt = 1;
                num[leg[i].d]--;
            }
        }
        printf("%d\n", sum - ans);
    }
    return 0;
}

D. Vitaly and Cycle

http://codeforces.com/contest/557/problem/D


题意:无向图,有n个端点m条边,求出至少加入多少条边可得到奇数环,且这样的环有多少个。

思路:分析题目可知只会有4种情况:

1. 加入0条边,将图进行二分图染色可以判断,若图不为二分图则无需加边,存在一个奇环。

2. 加入3条边,图中没有边的情况。

3.加入1条边,对图进行二分图染色的时候记录每个连通块的黑白点个数,形成奇环时 在同一个连通块中选择两个黑点或者两个白点,加入一条边得到奇环。

4.加入2条边,图不存在度大于等于2的点,则任选一个点和一条边 组成奇环,总数为 (n-2)*m。

AC.

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>

using namespace std;
const int maxn = 1e5+5;
vector<int> g[maxn];
int cnt[2], col[maxn];
int n, m;
vector<pair<int, int> > cal;

bool dfs(int u)
{
    for(int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i];
        if(col[v] != -1) {
            if(col[u] == col[v]) return false;
            else continue;
        }
        col[v] = col[u]^1;
        cnt[col[v]]++;
        if(!dfs(v)) return false;
    }
    return true;
}
bool judge()
{
    memset(col, -1, sizeof(col));
    for(int i = 0; i < n; ++i) {
        if(col[i] != -1) continue;
        col[i] = 0;
        cnt[0] = 1;
        cnt[1] = 0;
        if(!dfs(i)) return true;
        cal.push_back(make_pair(cnt[0], cnt[1]));
    }
    return false;
}
int main()
{
    //freopen("in", "r", stdin);
    while(~scanf("%d %d", &n, &m)) {
        for(int i = 0; i < n; ++i) {
            g[i].clear();
        }
        cal.clear();

        for(int i = 0; i < m; ++i) {
            int u, v;
            scanf("%d %d", &u, &v);
            u--; v--;
            g[u].push_back(v);
            g[v].push_back(u);
        }

        if(judge()) printf("0 1\n");
        else {
            int ok = 0;
            for(int i = 0; i < n; ++i) {
                if(g[i].size() > 1) {
                    ok = 1;
                    break;
                }
            }
            if(ok) {
                long long ans = 0;
                //printf("%d \n", cal[0].first, cal[0].second);
                for(int i = 0; i < cal.size(); ++i) {
                    ans += (long long)cal[i].first * (cal[i].first-1) / 2;
                    ans += (long long)cal[i].second * (cal[i].second - 1) / 2;
                }
                printf("1 %lld\n", ans);
            }
            else {
                if(m) {
                    printf("2 %I64d\n", (long long)m*(n-2));
                }
                else {
                    printf("3 %lld\n", (long long)n*(n-1)*(n-2)/6);
                }
            }
        }
    }
    return 0;
}


相关文章推荐

Codeforces Beta Round #27 (Codeforces format, Div. 2) D Ring Road 2(二分图染色版)

D. Ring Road 2 time limit per test 2 seconds memory limit per test 256 megabytes input s...

Codeforces Round #383 (Div. 2)E. Arpa’s overnight party and Mehrdad’s silent entering【二分图染色】

E. Arpa’s overnight party and Mehrdad’s silent entering time limit per test 1 second memo...

Codeforces Round #360 (Div. 2) 前三题题解【简单模拟+思维+二分图判定二分染色】

A. Opponents time limit per test 1 second memory limit per test 256 megabytes input...

AIM Tech Round (Div. 2) C. Graph and String(二分图染色 | 贪心)

题意: 给定一个N≤500的无向图,现要根据图还原一个字符串s1s2...sn,字符集只有a,b,c给定一个N\le 500的无向图, 现要根据图还原一个字符串s_1s_2...s_n, 字符集只...
  • lwt36
  • lwt36
  • 2016年02月05日 04:24
  • 402

Codeforces Round #360 (Div. 1) A. NP-Hard Problem(二分图染色)

题目链接:点击打开链接 思路:根据题目描述, 就是找两个不相交点集使得对于每一条边至少有一个顶点在点集中, 那么显然对于每条边必须是一个点在A集合, 一个点在B集合, 即二分图染色裸题。 WA了一...

Codeforces Round #360 (Div. 2) -- C. NP-Hard Problem (DFS二分图染色法)

C. NP-Hard Problem time limit per test 2 seconds memory limit per test 256 megabytes input standa...

Codeforces Round #365 (Div. 2) A(暴力) B(数学技巧) C(二分)D(线段树+离散)E(乘除法DP+约数分解+map映射)

传送门:A. Mishka and Game 暴力记录两人赢的次数,最后将次数再比较一次即可 #include using namespace std; int n; int main()...

Codeforces Round #311 (Div. 2) D. Vitaly and Cycle

题目链接:http://codeforces.com/contest/557/problem/D 题意:给你n个点,m条边,问你最少加几条边,使得有奇环(环的边数为奇数)存在,并输出共有几种方法。 ...

Codeforces Round #311 (Div. 2) C. Arthur and Table

C. Arthur and Table time limit per test 1 second memory limit per test 256 megabytes input standa...

Codeforces Round #311 (Div. 2) —— C

C. Arthur and Table time limit per test 1 second memory limit per test 256 megabytes input sta...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Codeforces Round #311 (Div. 2) C(技巧) *D(二分图染色)
举报原因:
原因补充:

(最多只允许输入30个字)