表达一下深深的怨念
题面保证了边权互不相同,然鹅我做这题的时候狂WA不止,对拍只有边权相同的时候能拍出来,交到uoj上也过了
我就怀疑数据有问题qwq
于是扒了一个AC代码,加了判如果有相同边权,输出了一些脏话qwq
然后0msWA了
注释掉这行
A掉了
…….
要了数据
这数据…一半以上一堆相同边权的吧….
边权互不相同保证了不考虑操作边的MST唯一,不保证相同边权…似乎不太可做?
辣鸡数据
题解部分:
我们先将可操作的边全部赋负权,建出原图的MST
这棵树上的正权边,无论你给操作边赋什么值都一定会在最终的MST上
所以用这些边将原图缩到O(k)个点,O(k^2)条边
再对缩点后的图建MST(不用那些操作边),这时MST上的边集S就是可能出现在最终的MST上的边
因为k不大,可以2^k枚举用哪些边,建出最终的MST
这时,因为kruskal的性质(联想建树的过程..),如果有一条边权为c的边(u,v)不在MST上,那么MST上的所有边权都<=c
我们只需要考虑S中的边对MST中的边权的影响(其他边不需要考虑,意会一下?),暴力在维护路径上操作边的边权
复杂度
O(mlogm+2kk2)
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
#define inf 1e6+1
using namespace std;
inline void read(int &x)
{
char c; while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
inline void down(int &x,const int &y){if(x>y)x=y;}
const int maxn = 210000;
const int maxm = 410000;
const int maxk = 25;
int n,m,K;
struct edge{int x,y,c;}a[maxm],b[maxk],c[maxn]; int an,bn,cn;
inline bool cmp(const edge x,const edge y){return x.c<y.c;}
int fa[maxn];
int findfa(const int x){return fa[x]==x?x:fa[x]=findfa(fa[x]);}
int idt[maxn]; ll num[maxn];
int pn,ci[maxk][maxk];
struct node{int y,i,nex;}e[maxm]; int len,fir[maxk];
inline void ins(const int x,const int y,const int i){e[++len]=(node){y,i,fir[x]};fir[x]=len;}
int val[maxk*2],fai[maxk];
int dep[maxk],Fa[maxn];
ll temp,siz[maxk];
void dfs(const int x)
{
siz[x]=num[x];
for(int k=fir[x],y=e[k].y;k;k=e[k].nex,y=e[k].y) if(y!=Fa[x])
{
dep[y]=dep[x]+1; Fa[y]=x;
if(e[k].i) fai[y]=e[k].i;
dfs(y);
siz[x]+=siz[y];
}
}
ll re;
int main()
{
read(n); read(m); read(K); an=m; bn=K;
for(int i=1;i<=m;i++) read(a[i].x),read(a[i].y),read(a[i].c);
for(int i=1;i<=bn;i++)
{
int x,y; read(x); read(y);
a[++an]=b[i]=(edge){x,y,-1};
}
sort(a+1,a+an+1,cmp);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=an;i++)
{
int x=a[i].x,y=a[i].y;
int f1=findfa(x),f2=findfa(y);
if(f1!=f2) fa[f1]=f2,c[++cn]=a[i];
}
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=cn;i++) if(c[i].c>0)
fa[findfa(c[i].x)]=findfa(c[i].y);
for(int i=1;i<=n;i++) if(findfa(i)==i)
idt[i]=++pn;
for(int i=1;i<=n;i++)
{
int x; read(x);
idt[i]=idt[findfa(i)],num[idt[i]]+=(ll)x;
}
memset(ci,63,sizeof ci);
for(int i=1;i<=an;i++) if(a[i].c>0)
{
int x=idt[findfa(a[i].x)],y=idt[findfa(a[i].y)];
if(x!=y) down(ci[x][y],a[i].c),down(ci[y][x],a[i].c);
}
cn=0;
for(int i=1;i<=pn;i++) for(int j=1;j<=pn;j++) if(ci[i][j]<inf)
c[++cn]=(edge){i,j,ci[i][j]};
sort(c+1,c+cn+1,cmp);
for(int i=1;i<=pn;i++) fa[i]=i;
an=0;
for(int i=1;i<=cn;i++)
{
int x=c[i].x,y=c[i].y;
int f1=findfa(x),f2=findfa(y);
if(f1!=f2) a[++an]=c[i],fa[f1]=f2;
}
re=0;
for(int i=1;i<(1<<bn);i++)
{
for(int j=1;j<=pn;j++) fa[j]=j,fai[j]=0;
for(int j=1;j<=pn;j++) fir[j]=0; len=0;
bool flag=true;
for(int j=1;j<=bn;j++) if(i>>j-1&1)
{
int x=idt[b[j].x],y=idt[b[j].y];
int f1=findfa(x),f2=findfa(y);
if(f1==f2) { flag=false; break; }
fa[f1]=f2;
ins(x,y,j*2+1); ins(y,x,j*2);
val[j*2+1]=val[j*2]=inf;
}
if(!flag) continue;
for(int j=1;j<=an;j++)
{
int x=a[j].x,y=a[j].y;
int f1=findfa(x),f2=findfa(y);
if(f1!=f2) ins(x,y,0),ins(y,x,0),fa[f1]=f2;
}
dep[idt[1]]=1; dfs(idt[1]);
temp=0;
for(int j=1;j<=an;j++)
{
int x=a[j].x,y=a[j].y;
if(dep[x]<dep[y]) swap(x,y);
while(dep[x]>dep[y])
{
if(fai[x]) down(val[fai[x]],a[j].c);
x=Fa[x];
}
while(x!=y)
{
if(fai[x]) down(val[fai[x]],a[j].c);
if(fai[y]) down(val[fai[y]],a[j].c);
x=Fa[x],y=Fa[y];
}
}
for(int j=1;j<=len;j++) if(e[j].i&&val[e[j].i]<inf) temp+=(ll)val[e[j].i]*siz[e[j].y];
re=max(re,temp);
}
printf("%lld\n",re);
return 0;
}