# 【次小生成树】bzoj1977 [BeiJing2010组队]次小生成树 Tree

5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6

11

## HINT

//by 减维
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<algorithm>
#define ll long long
#define ls l,mid,v<<1
#define rs mid+1,r,v<<1|1
#define getm mid=(l+r)>>1
using namespace std;

struct us{
int x,y;
ll v;
}edg[300005];

struct edge{
int to,ne;
ll v;
}e[200005];

int n,m,num,ecnt,fa[100005],dep[100005],siz[100005],son[100005],val[100005];
long long ans1,ans2,ans,ma[400005],ma2[400005];
bool pd[300005];
ll inf=1ll<<62;

bool cmp(const us&x,const us&y){return x.v<y.v;}
bool cm2(int x,int y){return x>y;}

int find(int x)
{
if(x==fa[x])return x;
fa[x]=find(fa[x]);
return fa[x];
}

{
e[++ecnt].to=y;
e[ecnt].v=z;
}

void df1(int x)
{
dep[x]=dep[f[x]]+1;
siz[x]=1;
{
int dd=e[i].to;
if(dd==f[x])continue;
f[dd]=x;
df1(dd);
siz[x]+=siz[dd];
if(!son[x]||siz[son[x]]<siz[dd])
son[x]=dd;
}
}

void dfs(int x,int tp)
{
top[x]=tp;
dfn[x]=++num;
if(son[x])dfs(son[x],tp);
{
int dd=e[i].to;
if(dd==f[x])continue;
if(dd==son[x]){
val[dfn[dd]]=e[i].v;
continue;
}
dfs(dd,dd);
val[dfn[dd]]=e[i].v;
}
out[x]=num;
}

void upda(int v)
{
int x[5];
x[1]=ma[v<<1],x[2]=ma[v<<1|1],x[3]=ma2[v<<1],x[4]=ma2[v<<1|1];
sort(x+1,x+5,cm2);
ma[v]=x[1];
ma2[v]=x[2];
}

void print(int l,int r,int v)
{
if(l==r){
printf("%d %d\n",ma[v],ma2[v]);
return ;
}
int mid;getm;
print(ls);
print(rs);
}

void build(int l,int r,int v)
{
if(l==r){
ma[v]=val[l];
ma2[v]=-inf;
return ;
}
int mid;getm;
build(ls);
build(rs);
upda(v);
}

ll ask(int l,int r,int v,int x,int y,int z)
{
if(r<x||y<l)return -inf;
if(x<=l&&r<=y){
if(ma[v]!=z)return ma[v];
return ma2[v];
}
int mid;getm;
}

int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
scanf("%d%d%lld",&edg[i].x,&edg[i].y,&edg[i].v);
sort(edg+1,edg+m+1,cmp);
for(int i=0;i<=n;++i)fa[i]=i;
int cntt=0;
for(int i=1;i<=m;++i)
{
int x=edg[i].x,y=edg[i].y;
int fx=find(x),fy=find(y);
if(fx!=fy){
cntt++;
pd[i]=1;
fa[fx]=fa[fy];
ans1+=edg[i].v;
}
if(cntt==n-1)break;
}
df1(1);
dfs(1,1);
build(1,num,1);
ans2=inf;
for(int i=1;i<=m;++i)
if(!pd[i]){
int x=edg[i].x,y=edg[i].y;
ll tmp=-inf;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]]){
x=f[top[x]];
}else {
y=f[top[y]];
}
}
int lca=dep[x]<dep[y]?x:y,deper=dep[x]>dep[y]?x:y;
ans2=min(ans2,ans1-tmp+edg[i].v);
}
printf("%lld",ans2);
}

【题目背景】

HJZ 买了一套新房子，他正在为新房子的装修发愁。

【题目描述】

【输入格式】

• 第一行两个整数 n, m 分别表示水管网的点数和预留的管道数。

• 接下来 m 行，每行三个正整数 a, b, c 表示一条连接 a, b 的双向管道需要 c 的 代价。

【输出格式】 输出到文件 pipe.out 中。 对于每一组测试数据，分别输出两行。

//by 减维
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<map>
#include<bitset>
#include<algorithm>
#define ll long long
using namespace std;

struct lin{
int fr,to,v;
}ed[200005];

struct edge{
int to,ne,v;
}e[200005];

struct node{
int v,pos;
}a[100005];

ll ans;
bool fla,pd[200005];

bool cmp(const lin&x,const lin&y){return x.v<y.v;}
bool cm2(const node&x,const node&y){
if(x.v==y.v)return x.pos<y.pos;
return x.v<y.v;
}

void init()
{
ecnt=num=tot=0;
ans=0;
fla=0;
memset(f,0,sizeof(f));
memset(pd,0,sizeof(pd));
memset(lx,0,sizeof(lx));
memset(rx,0,sizeof(rx));
memset(dep,0,sizeof(dep));
memset(son,0,sizeof(son));
memset(siz,0,sizeof(siz));
memset(dfn,0,sizeof(dfn));
memset(top,0,sizeof(top));
}

{
e[++ecnt].to=y;
e[ecnt].v=z;
}

int find(int x)
{
if(x==fa[x])return x;
fa[x]=find(fa[x]);
return fa[x];
}

void df1(int x)
{
siz[x]=1;
dep[x]=dep[f[x]]+1;
{
int dd=e[i].to;
if(dd==f[x])continue ;
f[dd]=x;
df1(dd);
siz[x]+=siz[dd];
if(!son[x]||siz[son[x]]<siz[dd])
son[x]=dd;
}
}

void dfs(int x,int tp)
{
top[x]=tp;
dfn[x]=++num;
if(son[x])dfs(son[x],tp);
{
int dd=e[i].to;
if(dd==f[x]||dd==son[x])continue;
dfs(dd,dd);
}
}

void df2(int x,int v)
{
a[++tot].v=v;
a[tot].pos=dfn[x];
{
int dd=e[i].to;
if(dd==f[x])continue;
df2(dd,e[i].v);
}
}

bool check(int x,int y,int v)
{
int l=lx[v],r=rx[v];
int mid;
while(l<=r){
mid=(l+r)>>1;
if(a[mid].pos<=y&&a[mid].pos>=x)return 1;
else if(a[mid].pos>y)r=mid-1;
else l=mid+1;
}
return 0;
}

int main()
{
freopen("pipe.in","r",stdin);
freopen("pipe.out","w",stdout);
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=m;++i)scanf("%d%d%d",&ed[i].fr,&ed[i].to,&ed[i].v);
sort(ed+1,ed+m+1,cmp);
for(int i=1;i<=n;++i)fa[i]=i;
int cnt=0;
for(int i=1,x,y,fx,fy;i<=m;++i)
{
x=ed[i].fr,y=ed[i].to;
fx=find(x),fy=find(y);
if(fx!=fy){
fa[fx]=fy;
cnt++;
ans+=(ll)ed[i].v;
pd[i]=1;
}
if(cnt==n-1)break;
}
printf("%lld\n",ans);
df1(1);
dfs(1,1);
df2(1,0);
sort(a+1,a+tot+1,cm2);
lx[a[1].v]=1;
for(int i=1;i<=tot;++i)
if(a[i].v!=a[i-1].v)lx[a[i].v]=i,rx[a[i-1].v]=i-1;
rx[a[tot].v]=tot;
for(int i=1,x,y,lca,v,deper;i<=m;++i)
if(!pd[i])
{
x=ed[i].fr,y=ed[i].to,v=ed[i].v;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
if(check(dfn[top[x]],dfn[x],v)){
fla=1;
break;
}
x=f[top[x]];
}
if(x!=y){
lca=dep[x]<dep[y]?x:y;
deper=lca==x?y:x;
if(check(dfn[son[lca]],dfn[deper],v))fla=1;
}
if(fla)break;
}
if(fla)printf("No\n");
else printf("Yes\n");
}
return 0;
}

posted @ 2017-10-17 14:56  减维  阅读(227)  评论(0编辑  收藏  举报