题意:
给你一张无向带权图,每次给你一个w,然后图中每条边的权值-w后取绝对值。并构造最小生成树。你的答案异或上这棵树的总权值,问你最后答案是多少。
题解:
我把+1写在了括号里,导致我找了一个多小时的bug,后面改着改着发现答案变了,于是开始研究这一块哪里能够导致答案变化,最终找到了这个bug…要是在比赛的时候这估计就找不到了,还是不够仔细啊。
首先我看完这道题目就发现n,m的范围很小,并且时限给了4s,怕是可以从这方面操作,我甚至能for一遍1e8!
然后发现了c的值<=1e8?那似乎我可以从这方面找突破口,要是它给了5e8我就歇菜了,估计正解也不是我这种方法…
那么我们是否能枚举每个值,然后做kruskal?很明显不能每次做,但是我们可以在关键位置做,什么是关键位置?也就是树的形状可能发生改变的时候。对于两条权重为a,b的边,当他们的取与否发生交换的时候可能会在(a+b)/2或者(a+b)/2+1的时候。这个时候原本权值小的边就变成大的边了。那么在这种时候我们才需要做kruskal。时间复杂度呢?
O
(
N
l
o
g
N
M
2
)
O(NlogNM^2)
O(NlogNM2)反正不会超。
那么对于做了kruskal的时候,答案当然是当前算出来的值啊,那之后呢?
我们可以发现,假设当前枚举到的值为i,然后我们知道上一次做完kruskal之后所有取出来的边的权重,假设权重<=i的边有x个,总共有y条边。那么i变成i+1的时候,是否x条边权值+1,y-x条边权值-1?
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define ll long long
const int N=55,M=305;
struct Edge{
int x,y, l,real;
bool operator<(const Edge& a)const {
return l<a.l;
}
}e[M],a[M];
int fa[N];
int finds(int x){return x==fa[x]?fa[x]:fa[x]=finds(fa[x]);}
bool hav[100000005];
int change[M*M];
int n,m,x,y,v,all,w[N];
int cal(int a,int b){return max(a,b)-min(a,b);}
ll kruskal(int x){
for(int i=1;i<=n;i++)fa[i]=i;
ll ans=0;
all=0;
for(int i=1;i<=m;i++)
e[i]={a[i].x,a[i].y,cal(a[i].l,x),a[i].l};
sort(e+1,e+1+m);
for(int i=1;i<=m;i++){
int fx=finds(e[i].x),fy=finds(e[i].y);
if(fx!=fy){
fa[fy]=fx;
ans+=e[i].l;
w[++all]=e[i].real;
}
}
sort(w+1,w+1+all);
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].l);
int tot=0;
for(int i=1;i<=m;i++)
for(int j=i+1;j<=m;j++)
change[++tot]=(a[i].l+a[j].l)/2,change[++tot]=(a[i].l+a[j].l)/2+1;
sort(change+1,change+1+tot);
tot=unique(change+1,change+1+tot)-change-1;
int p,k;
ll c,a,b;
scanf("%d%d%lld%lld%lld",&p,&k,&a,&b,&c);
ll q;
for(int i=1;i<=p;i++)scanf("%lld",&q),hav[q]^=1;
for(int i=p+1;i<=k;i++)
q=(q*a+b)%c,hav[q]^=1;
ll now=1,ans=0,last=kruskal(0),pos=1;
for(int i=0;i<c;i++){
if(now<=tot && change[now]<=i){
while(now<=tot&&change[now]<=i)now++;
last=kruskal(i);
pos=1;
}
if(hav[i])
ans^=last;
while(pos<=all&&w[pos]<=i)pos++;
last+=pos-1-all+pos-1;
}
printf("%lld\n",ans);
return 0;
}