[2017纪中10-28]图 最小生成树+LCT
2017-10-30 07:59
302 查看
题面
把图分成正图(k+x)和负图(k-x),且称正树为正图中的最小生成树,负树为负图中的最小生成树。
有个很明显的结论是,无论 x 的值是多少,最后的最小生成树的边一定是正图中的最小生成树上的边或负图的最小生成树上的边(因为正图和负图都是联通图)。
当 x 趋近于无穷小的时候,正树就是图的最小生成树,当 x 逐渐增大,负树中的边会逐渐取代正树中的边(但不一定按照从小到大顺序取代),例如样例。
但是这样并不影响我们从小到大加入负树中的边,因为上面的情况只会出现在两边产生的环没有边相交的情况,而如果有相交的部分,那么 k 比较小的会先做出决策。
然后就得到如下算法:
先分别做最小生成树算法得到正树和负树,以正树作为初始版本的最小生成树,然后将负树上的边从小到大加进生成树中,对于一条负边
把图分成正图(k+x)和负图(k-x),且称正树为正图中的最小生成树,负树为负图中的最小生成树。
有个很明显的结论是,无论 x 的值是多少,最后的最小生成树的边一定是正图中的最小生成树上的边或负图的最小生成树上的边(因为正图和负图都是联通图)。
当 x 趋近于无穷小的时候,正树就是图的最小生成树,当 x 逐渐增大,负树中的边会逐渐取代正树中的边(但不一定按照从小到大顺序取代),例如样例。
但是这样并不影响我们从小到大加入负树中的边,因为上面的情况只会出现在两边产生的环没有边相交的情况,而如果有相交的部分,那么 k 比较小的会先做出决策。
然后就得到如下算法:
先分别做最小生成树算法得到正树和负树,以正树作为初始版本的最小生成树,然后将负树上的边从小到大加进生成树中,对于一条负边
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define ll long long using namespace std; const int maxn=100010; const int maxm=200010; const int infk=1000000010; int n,a,b,Q,t,fa[maxn]; ll sum[maxm]; struct edge { int t,k,f; bool h; edge *next,*rev; }*con[maxn]; struct node { int u,v,k,f; edge *pt; }ea[maxm],eb[maxm],e[maxm]; struct node2 { ll s; int lx,tp; }d[maxm]; int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); return x*f; } void ins(int x,int y,int k,int f,bool h) { edge *p=new edge; p->t=y; p->k=k; p->f=f; p->h=h; p->next=con[x]; con[x]=p; } bool cmp(node a,node b) { return a.k+a.f*t<b.k+b.f*t; } bool cmp2(node2 a,node2 b) { return a.lx<b.lx; } int getfa(int v) { if(fa[v]==v) return v; fa[v]=getfa(fa[v]); return fa[v]; } void MST0(node *ex,int &sz) { int tot=0,chs=0; sort(ex+1,ex+sz+1,cmp); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=sz;i++) if(getfa(ex[i].u)!=getfa(ex[i].v)) { fa[getfa(ex[i].u)]=getfa(ex[i].v); ex[++tot]=ex[i]; chs++; if(chs>=n-1) break; } sz=tot; } ll MST(int &ttp) { sort(e+1,e+a+b+1,cmp); int chs=0;ttp=0;ll ans=0; for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=a+b;i++) if(getfa(e[i].u)!=getfa(e[i].v)) { fa[getfa(e[i].u)]=getfa(e[i].v); ans+=e[i].k+e[i].f*t; if(e[i].f==1) ttp++; chs++; if(chs>=n-1) break; } return ans; } bool find(int v,int fa,int goal,edge *&mxe) { bool re=0; for(edge *p=con[v];p;p=p->next) if(p->t!=fa&&p->h) { if(p->t==goal) re=1; else {re=re||find(p->t,v,goal,mxe);} if(re) { if((mxe==NULL||p->k>mxe->k)&&p->f==1) mxe=p; return 1; } } return 0; } int main() { freopen("graph.in","r",stdin); freopen("graph.out","w",stdout); n=read();a=read();b=read();Q=read(); for(int i=1;i<=a;i++) ea[i].u=read(),ea[i].v=read(),ea[i].k=read(),ea[i].f=1; for(int i=1;i<=b;i++) eb[i].u=read(),eb[i].v=read(),eb[i].k=read(),eb[i].f=-1; if(n>1000) { for(int i=1;i<=a;i++) e[i]=ea[i]; t=b=0; ll base=MST(b); while(Q--) { t=read(); printf("%lld\n",base+(ll)t*(n-1)); } } else { t=0; MST0(ea,a); MST0(eb,b); for(int i=1;i<=a;i++) { e[i]=ea[i]; ins(ea[i].u,ea[i].v,ea[i].k,ea[i].f,1); ins(ea[i].v,ea[i].u,ea[i].k,ea[i].f,1); con[ea[i].u]->rev=con[ea[i].v]; con[ea[i].v]->rev=con[ea[i].u]; ea[i].pt=con[ea[i].u]; } for(int i=1;i<=b;i++) { e[i+a]=eb[i]; ins(eb[i].u,eb[i].v,eb[i].k,eb[i].f,0); ins(eb[i].v,eb[i].u,eb[i].k,eb[i].f,0); con[eb[i].u]->rev=con[eb[i].v]; con[eb[i].v]->rev=con[eb[i].u]; eb[i].pt=con[eb[i].u]; } t=-1e9;d[0].s=MST(d[0].tp);d[0].lx=t; for(int i=1;i<=b;i++) { edge *mxe=NULL; find(eb[i].u,0,eb[i].v,mxe); mxe->h=mxe->rev->h=0; eb[i].pt->h=eb[i].pt->rev->h=1; t=ceil((double)(eb[i].k-mxe->k)/2+0.01); d[i].s=MST(d[i].tp);d[i].lx=t; d[i].tp-=(n-1-d[i].tp); } sort(d,d+b+1,cmp2); while(Q--) { t=read(); int l=0,r=b+1; while(l<r) { int mid=(l+r)>>1; if(d[mid].lx<=t) l=mid+1; else r=mid; } l--; printf("%lld\n",d[l].s+(ll)d[l].tp*(t-d[l].lx)); } } return 0; }
相关文章推荐
- 10-25 最小生成树——kruskal算法学习——经典例题及自编模版
- bzoj 3669 lct维护最小生成树
- 洛谷.4234.最小差值生成树(LCT)
- BZOJ2594 [Wc2006]水管局长数据加强版 【LCT维护最小生成树】
- BZOJ 2594: [Wc2006]水管局长数据加强版(LCT+最小生成树+离线)
- 迷之节约 分类: sdutOJ 最小生成树 2015-06-24 19:10 10人阅读 评论(0) 收藏
- ☆ [WC2006] 水管局长 「LCT动态维护最小生成树」
- POJ 3522 最小差值生成树(LCT)
- C++编程练习(10)----“图的最小生成树“(Prim算法、Kruskal算法)
- 3669 [Noi2014]魔法森林(LCT,最小生成树)
- C++编程练习(10)----“图的最小生成树“(Prim算法、Kruskal算法)
- BZOJ 2594 LCT维护最小生成树
- ☆ [NOI2014] 魔法森林 「LCT动态维护最小生成树」
- BZOJ3732:Network(LCT与最小生成树)
- bzoj 2594: [Wc2006]水管局长数据加强版(LCT+最小生成树+离线)
- PAT 5-10 公路村村通 && HDU 1232 Kruskal 最小生成树
- BZOJ3669(NOI2014):魔法森林 (LCT维护最小生成树)
- [GCD最小生成树 LCT] HDU5398 .GCD TREE
- [2017纪中10-30]Graph 最小生成树
- bzoj 1050 [HAOI2006]旅行comf [最小生成树] [动点spfa] [LCT]