【codeforces 796C】Bank Hacking

【题目链接】:http://codeforces.com/contest/796/problem/C

【题意】

给你n个节点,你一开始选择一个节点,然后打掉它,然后与被打掉过的节点相连的节点才能被
打掉,但打掉一个点之后,与它距离小于等于2的节点的权值会增加1(如果中间节点有被打掉的,则不增加,即被切断了);
重复上述步骤,直至所有节点被打掉,能打掉某个节点,你需要满足:你的权值大于等于这个节点的权值.求一开始你的
权值的最小值;

【题解】

枚举每一个点作为第一个打掉的点,除了和它距离为1的那些点权值只递增1之外,其他点都会递增2,用multiset维护除了这个点和距离为1的点之外的点的权值的最大值
用这个点权值a[i],距离为1的那些点的权值(a2[i]+1),以及multiset的(头结点的权值+2)这3个值中的最大值来获取你打掉所有节点且从第i个节点开始打需要的权值的最小值;
对于第一次选取的点只选最大值是有漏洞的如
3
3 2 3
1 2
2 3
选2的话答案更优为4
选3则为5了

【Number Of WA

4

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define ps push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%lld",&x)
#define ref(x) scanf("%lf",&x)
#define ms(x,y) memset(x,y,sizeof x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 3e5+100;

int a[N],n,ans=21e8;
vector <int> G[N];
multiset<int,greater<int>> myset;

void dele(int x)
{
    __typeof(myset.begin()) t;
    t = myset.find(x);
    myset.erase(t);
}

int main()
{
   // freopen("F:\\rush.txt","r",stdin);
    rei(n);
    rep1(i,1,n)
        rei(a[i]),myset.insert(a[i]);
    rep1(i,1,n-1)
    {
        int x,y;
        rei(x),rei(y);
        G[x].ps(y),G[y].ps(x);
    }
    rep1(i,1,n)
    {
        dele(a[i]);
        int ma = a[i];
        for (int y:G[i])
        {
            dele(a[y]);
            ma = max(ma,a[y]+1);
        }
        if (!myset.empty())
            ma = max(ma,*myset.begin()+2);
        for (int y:G[i])
            myset.insert(a[y]);
        myset.insert(a[i]);
        ans = min(ans,ma);
    }
    printf("%d\n",ans);
    //printf("\n%.2lf sec \n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}
posted @ 2017-10-04 18:44  AWCXV  阅读(105)  评论(0编辑  收藏  举报