bzoj 2563: 阿狸和桃子的游戏

Description

  阿狸和桃子正在玩一个游戏,游戏是在一个带权图G=(V, E)上进行的,设节点权值为w(v),边权为c(e)。游戏规则是这样的:
  1. 阿狸和桃子轮流将图中的顶点染色,阿狸会将顶点染成红色,桃子会将顶点染成粉色。已经被染过色的点不能再染了,而且每一轮都必须给一个且仅一个顶点染色。
  2. 为了保证公平性,节点的个数N为偶数。
  3. 经过N/2轮游戏之后,两人都得到了一个顶点集合。对于顶点集合S,得分计算方式为

  由于阿狸石头剪子布输给了桃子,所以桃子先染色。两人都想要使自己的分数比对方多,且多得越多越好。如果两人都是采用最优策略的,求最终桃子的分数减去阿狸的分数。

solution

正解:贪心
我们分析对答案的贡献,也就是对差的贡献,我们将边权拆成w/2,分别加到边对应的两个节点中,按照点权排序分别取,最后就是答案
分析为什么这样是对的:首先我们选择了一个点i,假设i对应的边边权为正无穷,考虑次大点j,如果阿狸选择j,那么就会失去i的边权,显然不是更优的,所以会选择另一条边,所以所有情况都能作出正确决策,满足最优性,所以就是答案

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
double w[10005];
void work()
{
   int x,y,z,n,m;cin>>n>>m;
   for(int i=1;i<=n;i++)scanf("%lf",&w[i]);
   for(int i=1;i<=m;i++){
      scanf("%d%d%d",&x,&y,&z);
      w[x]+=z/2.0;w[y]+=z/2.0;
   }
   sort(w+1,w+n+1);
   double s=0;int t=1;
   for(int i=n;i>=1;i--)
      s+=t*w[i],t*=-1;
   printf("%.lf\n",s);
}
 
int main()
{
    work();
    return 0;
}
posted @ 2017-10-22 23:49  Hxymmm  阅读(156)  评论(0编辑  收藏  举报