題目是給一個無向圖,其中每個節點都有點權,邊也有邊權,然後就有2個小朋友開始做游戲了ALICE &BOB 游戲規定ALICE 先行動然後是BOB,然後依次輪流行動,行動時可以任意選取一個節點並獲得節點的點權,如果他已經把一條邊的2個端點都取了,那麼他可以獲得那邊的邊權,如果一條邊的二個端點不同的人取了,那麼誰也得不到那條變得邊權了。 問游戲結束後怎樣可以使ALICE得到的權值和減去BOB 的權值和最大,當然二個人都一樣足夠聰明,即每次行動都會采取最優的策略
解法:若沒有邊權,則對點權從大到小排序即可。。考慮邊,將邊權拆成兩半加到它所關聯的兩個點的點權中即可。。。因為當兩個人分別選擇不同的點時,這一權值將互相抵消。
想想很好理解的,因為最後求的是差值。。。
需要注意的就是要用long long 別的就沒什麼了,為了避免拆邊時出現分數,可以算結果的2倍最後輸出的時候再除以2就行
下面是代碼:
#include<cstdio>
#include<algorithm>
bool inline cmp(long long a,long long b){return a>b;}//遞減排序的cmp函數
long long node[100005],ans;
int N,M;
int read()
{
if(scanf("%d%d",&N,&M)!=2) return 0;
for(int i=1;i<=N;i++)
{
scanf("%I64d",&node[i]);
node[i]*=2;//存2倍的點權
}
for(int a,b,c,i=0;i<M;i++)
{
scanf("%d%d%d",&a,&b,&c);
node[a]+=c,node[b]+=c;//拆邊就不用除以2了
}
std::sort(node+1,node+N+1,cmp);//遞減排序
ans=0;
for(int i=0;i<N/2;i++)
ans+=node[2*i+1]-node[2*i+2];//算結果
printf("%I64d\n",ans/2);//輸出的結果要除以二
return 1;
}
int main()
{
//freopen("in.txt","r",stdin);
while(read());
return 0;
}