NOIP模拟 图【最小生成树】
2017-11-07 20:50
260 查看
题目大意:
给n个点,m1条A边,m2条B边,A,B边所构成的图都是联通的;有q次询问,每次询问给出x,问将所有A边加上x,B边减去x后图中的最小生成树是多少。1<=n,q<=1000;
解题思路:
注意到当x为负无穷时答案就是A边构成的MST,为正无穷时就是B边构成的MST,所以当x逐渐增大,B边构成的MST上的边就会逐渐取代A边构成的MST上的边。而最优的肯定是小的B边先加进去取代路径上最大的A边。所以我们可以按B边从小到大的顺序算出加进每条B边时的x的下界,同时不断修改树的形态即可。而且这样如果两条B边影响的路径有交集,其x的下界是递增的,而如果没有交集,x虽不是递增的,但不影响另一条边所替换的A边,可是会影响当前MST的大小。所以最后才能把替换操作按x从小到大排序后计算当前x下MST的大小。
然后把询问也按x从小到大排序后计算当前x下MST的大小即可。
由于修改树的形态是O(n)的(LCT可优化到O(logn)),所以做复杂度为O(n2)
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cmath> #include<vector> #include<queue> #define ll long long using namespace std; int getint() { int i=0,f=1;char c; for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar()); if(c=='-')f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0'; return i*f; } const int N=100005,M=200005,INF=0x3f3f3f3f; int n,m1,m2,Q; int fa ,len ,stk ,visit ; int tot,first ,nxt[M],to[M],w[M]; ll totlen,ans ; bool exist[M]; struct edge { int x,y 14561 ,w; friend inline bool operator <(const edge &a,const edge &b) {return a.w<b.w;} }bian1[M],bian2[M]; struct node { int x,w1,w2;ll val; friend inline bool operator <(const node &a,const node &b) {return a.x<b.x;} }upt[M]; struct node1 { int x,id; friend inline bool operator <(const node1 &a,const node1 &b) {return a.x<b.x;} }q ; int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } void add(int x,int y,int z) { nxt[++tot]=first[x],first[x]=tot,to[tot]=y,w[tot]=z; } void kruskal1() { for(int i=1;i<=n;i++)fa[i]=i; sort(bian1+1,bian1+m1+1); int k=0; for(int i=1;i<=m1;i++) { int x=find(bian1[i].x),y=find(bian1[i].y); if(x!=y) { k++;totlen+=bian1[i].w; add(bian1[i].x,bian1[i].y,bian1[i].w); add(bian1[i].y,bian1[i].x,bian1[i].w); fa[y]=x; } if(k==n-1)break; } } void kruskal2() { for(int i=1;i<=n;i++)fa[i]=i; sort(bian2+1,bian2+m2+1); int k=0; for(int i=1;i<=m2;i++) { int x=find(bian2[i].x),y=find(bian2[i].y); if(x!=y)k++,exist[i]=true,fa[y]=x; if(k==n-1)break; } int cnt=0; for(int i=1;i<=m2;i++) if(exist[i])bian2[++cnt]=bian2[i]; m2=cnt; memset(fa,0,sizeof(fa)); } void dfs(int u) { for(int e=first[u];e;e=nxt[e]) { int v=to[e]; if(v==fa[u])continue; fa[v]=u;len[v]=w[e]; dfs(v); } } void solve(int i) { int x=bian2[i].x,y=bian2[i].y,mx=-INF,pos,top,bz=2; visit[x]=i; while(fa[x])visit[fa[x]]=i,x=fa[x]; while(visit[y]!=i) { if(len[y]>mx)mx=len[y],pos=y,bz=2; y=fa[y]; } x=bian2[i].x; while(x!=y) { if(len[x]>mx)mx=len[x],pos=x,bz=1; x=fa[x]; } upt[i].w1=mx,upt[i].w2=bian2[i].w,upt[i].x=(bian2[i].w-mx+1)/2; x=bian2[i].x,y=bian2[i].y,top=0; if(bz==2)swap(x,y); while(x!=fa[pos])stk[++top]=x,x=fa[x]; for(int j=top;j>1;j--)fa[stk[j]]=stk[j-1],len[stk[j]]=len[stk[j-1]]; x=stk[1],fa[x]=y,len[x]=-INF; } int main() { //freopen("mst.in","r",stdin); //freopen("mst.out","w",stdout); n=getint(),m1=getint(),m2=getint(),Q=getint(); for(int i=1;i<=m1;i++)bian1[i].x=getint(),bian1[i].y=getint(),bian1[i].w=getint(); for(int i=1;i<=m2;i++)bian2[i].x=getint(),bian2[i].y=getint(),bian2[i].w=getint(); kruskal1(),kruskal2(),dfs(1); for(int i=1;i<=m2;i++) solve(i); sort(upt+1,upt+n); upt[0].x=-INF,upt[0].val=totlen-1ll*(n-1)*INF,upt .x=INF; for(int i=1;i<n;i++) upt[i].val=upt[i-1].val+1ll*(n-i*2+1)*(upt[i].x-upt[i-1].x)-(upt[i].w1+upt[i].x)+(upt[i].w2-upt[i].x); for(int i=1;i<=Q;i++)q[i].x=getint(),q[i].id=i; sort(q+1,q+Q+1); int p=0; for(int i=1;i<=Q;i++) { while(q[i].x>=upt[p+1].x)p++; ans[q[i].id]=upt[p].val+1ll*(n-p*2-1)*(q[i].x-upt[p].x); } for(int i=1;i<=Q;i++) cout<<ans[i]<<'\n'; return 0; }
相关文章推荐
- NOIP2017模拟 玩游戏 最小生成树 树上倍增
- [NOIP模拟][最小生成树]Roads
- 【NOIP2015模拟11.4】电话线铺设 jzoj 4313 最小生成树+树链剖分
- 【图-最小生成树】NOIP2010 模拟试题 新的开始
- NOIP2013模拟最小比例
- NOIP2013 货车运输 [LCA] [RMQ] [最小生成树] [ST倍增]
- 【题解】NOIP 2013 货车运输(最小生成树+LCA)
- ZOJ 【2108】Agri-Net(最小生成树)模拟生成树&普利姆算法
- 【NOIP2011模拟9.17】数字生成游戏
- Hihocoder 之 #1097 : 最小生成树一·Prim算法 (用vector二维 模拟邻接表,进行prim()生成树算法, *【模板】)
- 10.3 NOIP模拟赛 DP + 最小生成树 + 容斥
- 【NOIP2017提高A组模拟10.8】Star Way To Heaven(欧几里得距离最小生成树Prim做法)
- jzoj 2570. 【NOIP2011模拟9.17】数字生成游戏
- NOIP2017 7.17模拟 Minimum (最短路+最小生成树)
- NOIP复习-006——最小生成树
- 【NOIP2015模拟10.22】最小代价
- JZOJ4735【NOIP2016提高A组模拟8.24】最小圈 Spfa深搜判负环
- 【NOIP模拟赛】藏宝图 最小生成树
- 高中OJ3514. 【NOIP2013模拟11.6B组】最小比例
- 【NOIP 模拟题】最小生成树(Tarjan求桥)