Problem Toll Management IV
题目大意
给一张n个点m条边的无向图,有边权。数据保证前n-1条边构成了一棵最小生成树。
要求对于每条边求出其边权上下最多浮动范围,使得最小生成树的形态不变(每次只改变一条边的权值)。
n<=10000,m<=1000000
解题分析
我们称在最小生成树上的边为实边,不在最小生成树上的边为虚边。
对于虚边u-->v,其权值一定可以无限增加。可以发现这条虚边不会影响u--v路径外的点所构成最小生成树的形态。假设u-->v路径上的边最大权值为w,那么当这条虚边的权值小于w时,那么这条虚边将会取代权值为w的边,成为实边。即这条虚边权值的下限为w。
对于实边u-->v,其权值一定可以无限减小。假设不选用这条实边,那么最小生成树将被分成两部分。那么连接这两部分的虚边将有可能替代这条实边。假设有可能的虚边中权值最小为w,那么这条实边的上限为w。
参考程序
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <map> 2 #include <set> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <string> 8 #include <vector> 9 #include <cstdio> 10 #include <cstdlib> 11 #include <cstring> 12 #include <cassert> 13 #include <iostream> 14 #include <algorithm> 15 #pragma comment(linker,"/STACK:102400000,102400000") 16 using namespace std; 17 18 #define V 10008 19 #define E 200008 20 #define LL long long 21 #define lson l,m,rt<<1 22 #define rson m+1,r,rt<<1|1 23 #define clr(x,v) memset(x,v,sizeof(x)); 24 #define bitcnt(x) __builtin_popcount(x) 25 #define rep(x,y,z) for (int x=y;x<=z;x++) 26 #define repd(x,y,z) for (int x=y;x>=z;x--) 27 const int mo = 1000000007; 28 const int inf = 0x3f3f3f3f; 29 const int INF = 2000000000; 30 /**************************************************************************/ 31 int n,m,sum,cnt; 32 int lt[V],dep[V],son[V],w[V],rk[V],fa[V],top[V],size[V]; 33 int a[E],b[E]; 34 35 struct line{ 36 int u,v,w,nt; 37 line(int u=0,int v=0,int w=0,int nt=0):u(u),v(v),w(w),nt(nt){} 38 }eg[E],EG[E]; 39 void add(int u,int v,int w){ 40 eg[++sum]=line(u,v,w,lt[u]); lt[u]=sum; 41 } 42 void dfs_1(int u){ 43 dep[u]=dep[fa[u]]+1; size[u]=1; son[u]=0; 44 for (int i=lt[u];i;i=eg[i].nt){ 45 int v=eg[i].v; 46 if (v==fa[u]) continue; 47 fa[v]=u; 48 dfs_1(v); 49 if (size[v]>size[son[u]]) son[u]=v; 50 size[u]+=size[v]; 51 } 52 } 53 void dfs_2(int u,int tp){ 54 top[u]=tp; w[u]=++cnt; rk[cnt]=u; 55 if (son[u]) dfs_2(son[u],tp); 56 for (int i=lt[u];i;i=eg[i].nt){ 57 int v=eg[i].v; 58 if (v==fa[u]||v==son[u]) continue; 59 dfs_2(v,v); 60 } 61 } 62 struct Segment_Tree{ 63 int mx[V<<2],lazy[V<<2]; 64 inline void pushup(int rt){ 65 mx[rt]=max(mx[rt<<1],mx[rt<<1|1]); 66 } 67 inline void pushdown(int rt){ 68 if (lazy[rt]!=-INF){ 69 lazy[rt<<1]=max(lazy[rt<<1],lazy[rt]); 70 lazy[rt<<1|1]=max(lazy[rt<<1|1],lazy[rt]); 71 mx[rt<<1]=max(mx[rt<<1],lazy[rt]); 72 mx[rt<<1|1]=max(mx[rt<<1|1],lazy[rt]); 73 lazy[rt]=-INF; 74 } 75 } 76 void build(int l,int r,int rt){ 77 mx[rt]=-INF; lazy[rt]=-INF; 78 if (l==r) return; 79 int m=(l+r)>>1; 80 build(lson); 81 build(rson); 82 pushup(rt); 83 } 84 void update(int L,int R,int val,int l,int r,int rt){ 85 if (L<=l && r<=R){ 86 lazy[rt]=max(val,lazy[rt]); 87 mx[rt]=max(mx[rt],val); 88 return; 89 } 90 pushdown(rt); 91 int m=(l+r)>>1; 92 if (L <= m) update(L,R,val,lson); 93 if (m < R) update(L,R,val,rson); 94 pushup(rt); 95 } 96 int query(int L,int R,int l,int r,int rt){ 97 if (L<=l && r<=R){ 98 return mx[rt]; 99 } 100 pushdown(rt); 101 int m=(l+r)>>1; 102 int res=-INF; 103 if (L <= m) res=max(res,query(L,R,lson)); 104 if (m < R) res=max(res,query(L,R,rson)); 105 return res; 106 } 107 }T1,T2; 108 int find(int x,int y){ 109 int res=-INF; 110 while (top[x]!=top[y]){ 111 if (dep[top[x]]<dep[top[y]]) swap(x,y); 112 res=max(res,T1.query(w[top[x]],w[x],1,n,1)); 113 x=fa[top[x]]; 114 } 115 if (dep[x]>dep[y]) swap(x,y); 116 res=max(res,T1.query(w[x]+1,w[y],1,n,1)); 117 return res; 118 } 119 void change(int x,int y,int val){ 120 while (top[x]!=top[y]){ 121 if (dep[top[x]]<dep[top[y]]) swap(x,y); 122 T2.update(w[top[x]],w[x],val,1,n,1); 123 x=fa[top[x]]; 124 } 125 if (dep[x]>dep[y]) swap(x,y); 126 T2.update(w[x]+1,w[y],val,1,n,1); 127 } 128 int main(){ 129 int T,cas=0; 130 scanf("%d",&T); 131 while (T--){ 132 clr(lt,0); sum=1; cnt=0; 133 134 scanf("%d%d",&n,&m); 135 for (int i=1;i<n;i++){ 136 int u,v,w; 137 scanf("%d%d%d",&u,&v,&w); 138 add(u,v,w); add(v,u,w); 139 EG[i]=line(u,v,w); 140 } 141 for (int i=n;i<=m;i++){ 142 int u,v,w; 143 scanf("%d%d%d",&u,&v,&w); 144 EG[i]=line(u,v,w); 145 } 146 dfs_1(1); 147 dfs_2(1,1); 148 T1.build(1,n,1); 149 T2.build(1,n,1); 150 for (int i=1;i<n;i++){ 151 if (dep[EG[i].u]>dep[EG[i].v]) swap(EG[i].u,EG[i].v); 152 T1.update(w[EG[i].v],w[EG[i].v],EG[i].w,1,n,1); 153 } 154 for (int i=n;i<=m;i++){ 155 int tmp=find(EG[i].u,EG[i].v); 156 b[i]=tmp==-INF?-1:EG[i].w-tmp; 157 change(EG[i].u,EG[i].v,-EG[i].w); 158 } 159 for (int i=1;i<n;i++){ 160 int tmp=T2.query(w[EG[i].v],w[EG[i].v],1,n,1); 161 a[i]=tmp==-INF?-1:-tmp-EG[i].w; 162 } 163 LL res=0; 164 for (int i=1;i<n;i++) res=res+1ll*i*a[i]+1ll*i*i*-1; 165 for (int i=n;i<=m;i++) res=res+1ll*i*-1+1ll*i*i*b[i]; 166 167 printf("Case %d: %lld\n",++cas,res ); 168 } 169 }