题目链接:HDU4647
题目大意:有n个点和m条边,每个点有权值,每条边有权值,规则如下,如果要得到点的权值只需要选中那个点即可,如果想得到边权值,必须把这条边的两格点都选中才行,选过的点不能再被选中,Alice先选,Bob后选,每次选都是最优解,求最后Alice的权值-Bob的权值
思路:最后要求的是A-B,怎么处理边呢, 这样想,一条边的两个点如果被A选中,那么A-B=w(边权),如果A,B各自选中的这条边的一个点,那么这条边对A-B不做贡献,或者说抵消了,所以 ,我们可以把这条边的权值平分给相邻的两个点,拆边,不影响最后的结果。A+w/2-(B+w/2)=A-B A+w/2+w/2-B=w
然后将所有点排序,A先选最大的,然后B选下一个,这样模拟一下就过了。
AC代码:
/*
2017年8月2日15:20:17
HDU4647
AC
*/
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
double v[maxn];
ll n,m;
int main(){
while(~scanf("%I64d%I64d",&n,&m)){
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++){
scanf("%lf",&v[i]);
}
ll a,b;
double c;
if(m){
for(int i=1;i<=m;i++){
scanf("%I64d%I64d%lf",&a,&b,&c);
v[a]+=1.0*c/2.0;
v[b]+=1.0*c/2.0;
}
}
sort(v+1,v+n+1);
double alice=0.0,bob=0.0;
bool flag=1;
double res=0;
for(int i=n;i>0;i--){
if(flag){
res+=v[i];
flag=!flag;
}
else{
res-=v[i];
flag=!flag;
}
}
printf("%.lf\n",res);
}
return 0;
}