BZOJ-2563 阿狸和桃子的游戏(贪心)
题目描述
给定一张 $n \((\)n\leq 10^4$,且 \(n\) 一定为偶数) 个点,\(m(1\leq m\leq 10^5)\) 条边的无向图,每个点有点权,每条边有边权(可能为负值),两个人轮流选择点,若一条边的两端点被选择则这条边被选择,两人都想自己的得分减对手的得分最大,求最终先手得分减后手得分。
分析
贪心策略:将每条边的两个端点分别加上这条边一半的边权,排序后轮流取最大值。
证明:
对于一条边 \(edge(x,y,z)\),设两端点的点权为 \(a_x,a_y\),加上一半边权后变成 \(a_{x}+\frac{z}{2},a_{y}+\frac{z}{2}\)。
分以下几种情况讨论:
\(1.\) 点 \(x\) 和点 \(y\) 被同一人取到,此人获得的权值为 \(a_x+\frac{z}{2}+a_y+\frac{z}{2}=a_x+a_y+z\)。
\(2.\) 点 \(x\) 和点 \(y\) 分别被两人取到,一人获得的权值为 \(a_x+\frac{z}{2}\),另一人获得的权值为 \(a_y+\frac{z}{2}\),权值之差为 \(a_x-a_y\)。
综上所述,贪心策略正确。
代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
double a[100010];
bool cmp(double A,double B)
{
return A>B;
}
double sum1,sum2;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
a[x]=a[x]+z/2.0;
a[y]=a[y]+z/2.0;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
{
if(i%2==1)
sum1=sum1+a[i];
else
sum2=sum2+a[i];
}
cout<<sum1-sum2<<endl;
return 0;
}
posted on 2020-12-03 21:23 DestinHistoire 阅读(99) 评论(0) 收藏 举报