题意:给定N的顶点,M条边的无向图。有点权,边权。
两个人轮流选点,最终所得分数为所选点权和+边(两端点都被选)权的总和。采取最优策略,使得自己的分数-对手的分数最大。。
问先行者分数-后行者分数的最大值。。
Mark:比赛的时候就想到把边权拆分到点上,各为w/2,脑残地忘记使用double了。。。然后依据点权排序,从大到小,轮流选即可。。。。。做难题,就是需要多去分析,多想,而不是坐一边就没事干了。。。难题如何入手?多想,多分析。。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define LL long long #define N 200010 struct edge{ int v,u; LL val; }e[N]; int tot; LL a[N]; struct tada{ double s; int pos; }seq[N]; int n,m; int vis[N]; bool cmp(tada p, tada q){ return p.s > q.s; } void add(int u,int v,LL val){ e[tot].u = u; e[tot].v = v; e[tot].val = val; tot++; return ; } int main() { while (scanf("%d%d",&n,&m)==2){ tot = 0; for (int i=1;i<=n;i++){ scanf("%I64d",&a[i]); seq[i].s = a[i]; seq[i].pos = i; } for (int i=1;i<=m;i++){ int u,v; LL w; scanf("%d%d%I64d",&u,&v,&w); add(u,v,w); seq[u].s += w/2.0; seq[v].s += w/2.0; } sort(seq+1,seq+1+n,cmp); LL ans = 0; double sum = 0; memset(vis,0,sizeof(vis)); for (int i=1;i<=n;i++) { if (i % 2==1){ ans += a[seq[i].pos]; vis[seq[i].pos] = 1; sum += seq[i].s; }else{ ans -= a[seq[i].pos]; sum -= seq[i].s; } } for (int i=0;i<m;i++) { int u = e[i].u; int v = e[i].v; LL val = e[i].val; if (vis[u]==vis[v]){ if (vis[u]==1) ans += val; else ans -= val; } } printf("%I64d\n",ans); } return 0; }