注意到k很小,那么我们把这给定的k条边设为-inf跑最小生成树,此时最小生成树中非这k条边的边是一定要加入最终的最小生成树的,那么可以将点缩在一起,这样就只剩下k+1个点了。然后对原图中的点跑最小生成树(缩点后的最小生成树),此时最小生成树中的边是可能要选的。那么就只剩下k条边了。
然后就可以2^k枚举要选的边的子集,注意要选的边不能构成环。然后就得到了一颗树,随便乱搞一下就好可。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define M 300005
#define ll long long
using namespace std;
int n,m,cnt,tot,tp,rt,bin[35],c[35],fa[2][N],f[N],d[N],fst[N],pnt[105],nxt[105]; ll sz[N],val[N];
struct node{ int x,y,z; }a[M],b[35];
int read(){
int x=0; char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); }
return x;
}
bool cmp(node u,node v){ return u.z<v.z; }
int getfa(int k,int x){ return (fa[k][x]==x)?x:fa[k][x]=getfa(k,fa[k][x]); }
void dfs(int x){
sz[x]=val[x]; int p;
for (p=fst[x]; p; p=nxt[p]){
int y=pnt[p];
if (y!=fa[1][x]){
fa[1][y]=x; d[y]=d[x]+1; dfs(y);
sz[x]+=sz[y];
}
}
}
void add(int x,int y){
pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot;
}
int main(){
n=read(); m=read(); cnt=read(); int i;
for (i=1; i<=m; i++){
a[i].x=read(); a[i].y=read(); a[i].z=read();
}
sort(a+1,a+m+1,cmp);
for (i=1; i<=n; i++) fa[0][i]=fa[1][i]=i;
for (i=1; i<=cnt; i++){
b[i].x=read(); b[i].y=read();
int u=getfa(0,b[i].x),v=getfa(0,b[i].y);
if (u!=v) fa[0][u]=v;
}
for (i=1; i<=m; i++){
int u=getfa(0,a[i].x),v=getfa(0,a[i].y);
if (u!=v){ fa[0][u]=v; fa[1][getfa(1,a[i].x)]=getfa(1,a[i].y); }
}
rt=getfa(1,1);
for (i=1; i<=n; i++) val[getfa(1,i)]+=read();
for (i=1; i<=n; i++) if (getfa(1,i)==i) c[++c[0]]=i;
for (i=1; i<=cnt; i++){
b[i].x=getfa(1,b[i].x); b[i].y=getfa(1,b[i].y);
}
for (i=1; i<=m; i++){
a[i].x=getfa(1,a[i].x); a[i].y=getfa(1,a[i].y);
}
for (i=1; i<=m; i++){
int u=getfa(1,a[i].x),v=getfa(1,a[i].y);
if (u!=v){ fa[1][u]=v; a[++tp]=a[i]; }
}
ll ans=0; int k;
bin[0]=1; for (i=1; i<=cnt; i++) bin[i]=bin[i-1]<<1;
for (k=0; k<bin[cnt]; k++){
tot=0;
for (i=1; i<=c[0]; i++){
int x=c[i]; fst[x]=fa[1][x]=0;
fa[0][x]=x; f[x]=1000000000;
}
for (i=1; i<=cnt; i++)
if (k&bin[i-1]){
int u=getfa(0,b[i].x),v=getfa(0,b[i].y);
if (u==v) break; fa[0][u]=v;
add(b[i].x,b[i].y); add(b[i].y,b[i].x);
}
if (i<=cnt) continue;
for (i=1; i<=cnt; i++){
int u=getfa(0,a[i].x),v=getfa(0,a[i].y);
if (u!=v){ fa[0][u]=v; add(a[i].x,a[i].y); add(a[i].y,a[i].x); }
}
dfs(rt);
for (i=1; i<=cnt; i++){
int u=a[i].x,v=a[i].y;
if (d[u]<d[v]) swap(u,v);
for (; d[u]!=d[v]; u=fa[1][u]) f[u]=min(f[u],a[i].z);
for (; u!=v; u=fa[1][u],v=fa[1][v]){
f[u]=min(f[u],a[i].z); f[v]=min(f[v],a[i].z);
}
}
ll tmp=0;
for (i=1; i<=cnt; i++) if (k&bin[i-1]){
int u=b[i].x,v=b[i].y;
if (d[u]<d[v]) swap(u,v); tmp+=sz[u]*f[u];
}
ans=max(ans,tmp);
}
printf("%lld\n",ans);
return 0;
}
by lych
2016.4.6