题目:给一个无向图,其中每个节点都有点权,边也有边权,然后就有2个小朋友开始做游戏了ALICE &BOB 游戏规定ALICE 先行动然后是BOB,然后依次轮流行动,行动时可以任意选取一个节点并获得节点的点权,如果他已经把一条边的2个端点都取了,那么他可以获得那边的边权,如果一条边的二个端点不同的人取了,那么谁也得不到那条变得边权了。 问游戏结束后怎样可以使ALICE得到的权值和减去BOB 的权值和最大,当然二个人都一样足够聪明,即每次行动都会采取最优的策略
解法:若没有边权,则对点权从大到小排序即可。。考虑边,将边权拆成两半加到它所关联的两个点的点权中即可。。。因为当两个人分别选择不同的点时,这一权值将互相抵消。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 ",ans/2); } return 0; }