bzoj 3206: [Apio2013]道路费用 最小生成树

来源:互联网 发布:最好的桌面主题软件 编辑:程序博客网 时间:2024/05/21 12:41

       注意到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 longusing 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

0 0
原创粉丝点击