hdu4647(思路啊!)

题目:给一个无向图,其中每个节点都有点权,边也有边权,然后就有2个小朋友开始做游戏了ALICE &BOB 游戏规定ALICE 先行动然后是BOB,然后依次轮流行动,行动时可以任意选取一个节点并获得节点的点权,如果他已经把一条边的2个端点都取了,那么他可以获得那边的边权,如果一条边的二个端点不同的人取了,那么谁也得不到那条变得边权了。 问游戏结束后怎样可以使ALICE得到的权值和减去BOB 的权值和最大,当然二个人都一样足够聪明,即每次行动都会采取最优的策略

解法:若没有边权,则对点权从大到小排序即可。。考虑边,将边权拆成两半加到它所关联的两个点的点权中即可。。。因为当两个人分别选择不同的点时,这一权值将互相抵消。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<vector>
#define tree int o,int l,int r
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define lo o<<1
#define ro o<<1|1
#define ULL unsigned long long
#define LL long long
#define UI unsigned int
#define inf 0x7fffffff
#define eps 1e-7
#define M 9901
#define N 100009
using namespace std;
int T,n,m,k,t,maxv;
LL a[N];
void init()
{
    memset(a,0,sizeof(a));
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("ex.in","r",stdin);
#endif
    int ncase=0;
    while(scanf("%d%d",&n,&m)==2)
    {
        init();
        for(int i=1; i<=n; i++)
        {
            scanf("%I64d",&a[i]);
            a[i]*=2;
        }
        while(m--)
        {
            int x,y;
            LL v;
            scanf("%d%d%I64d",&x,&y,&v);
            a[x]+=v;
            a[y]+=v;
        }
        sort(a+1,a+n+1);
        LL ans=0;
        for(int i=1; i<=n; i++)
            ans+=(i&1)?-1*a[i]:1*a[i];
        printf("%I64d\n",ans/2);
    }
    return 0;
}
View Code

 

posted @ 2013-08-11 20:04  baoff  阅读(196)  评论(0编辑  收藏  举报