Codeforces Round #158 (Div. 2)D. Black and White Tree(搜索 + 思維)

題目鏈接

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

題目大意

給你一棵樹(注意不要出現環)的所有節點, 節點分爲黑、白兩類,只有不同顏色的節點才能相連, 每個節點還有一個值, 該值表示該點所連邊的權值之和, 最後讓你輸出每條邊所連的兩個節點以及其權值(題目爲特判)

思路

該題幾乎沒有用到算法,但十分考驗思維
首先sum(edge) = sum(node)
由於只有不同顏色的node才能相連, 所以sum(white) = sum(black)

由這兩個式子我們可以得出這麼一個結論:從一個節點出發, 取另一種顏色的另一個節點, 我們把較小的值作爲該邊的權值,那麼較大的就要減去這個權值, 再用已經減過的值繼續遞歸地找另一種顏色的節點, 這樣一定可以組成一張符合題意的樹, 如果還有節點沒有使用,那麼該節點的值一定爲0, 否則就無法加入樹中

有很多題解都是排序後貪心找, 其實不用排序, 直接dfs就好了

代碼

#include<bits/stdc++.h>
using namespace std;

const int M = 1e5 + 5;

struct node
{
    int id, val;
    bool operator < (node & x)
    {
        return val < x.val;
    }
};
queue<node>b;
queue<node>w;

struct edg
{
    int l, r, val;
};
vector<edg>ans;

void dfs(node v, bool c)
{
    if(c)
    {
        while(!b.empty())
        {
            node tmb = b.front();
            b.pop();
            edg tmp;
            if(tmb.val >= v.val)
            {
                tmp.l = v.id;
                tmp.r = tmb.id;
                tmp.val = v.val;
                ans.push_back(tmp);
                tmb.val -= v.val;
                dfs(tmb, 0);
                return ;
            }
            tmp.l = tmb.id;
            tmp.r = v.id;
            tmp.val = tmb.val;
            ans.push_back(tmp);
            v.val -= tmb.val;
        }

    }
    else
    {
        while(!w.empty())
        {
            node tmw = w.front();
            w.pop();
            edg tmp;
            if(tmw.val > v.val)
            {
                tmp.l = v.id;
                tmp.r = tmw.id;
                tmp.val = v.val;
                ans.push_back(tmp);
                tmw.val -= v.val;
                dfs(tmw, 1);
                return ;
            }
            tmp.l = tmw.id;
            tmp.r = v.id;
            tmp.val = tmw.val;              
            ans.push_back(tmp);
            v.val -= tmw.val;
        }
    }
}

int main()
{
    int n;
    scanf("%d", &n);
    int tb = 0, tw = 0;
    for(int i=1; i<=n; ++i)
    {
        int c, v;
        scanf("%d%d", &c, &v);
        if(c)
        {
            node tmp;
            tmp.id = i;
            tmp.val = v;
            b.push(tmp);
        }
        else
        {
            node tmp;
            tmp.id = i;
            tmp.val = v;
            w.push(tmp);
        }
    }
    int rw = w.front().id, rb = b.front().id;
    node temp = b.front();
    b.pop();
    dfs(temp, 0);
    while(w.size())   //注意最後可能還有節點沒有用完,這些沒用完的節點的值一定是0,否則那兩個式子就不成立了
    {
        node tmw = w.front();
        w.pop();
        edg tmp;
        tmp.l = tmw.id;
        tmp.r = rb;
        tmp.val = 0;
        ans.push_back(tmp);
    }
    while(b.size())
    {
        node tmb = b.front();
        b.pop();
        edg tmp;
        tmp.l = tmb.id;
        tmp.r = rw;
        tmp.val = 0;
        ans.push_back(tmp);
    }
    int len = ans.size();
    for(int i=0; i<len; ++i)
    {
        printf("%d %d %d\n", ans[i].l, ans[i].r, ans[i].val);
    }
    return 0;
}
發佈了54 篇原創文章 · 獲贊 13 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章