http://codeforces.com/contest/733/problem/F
题意:给你一些城市和一些路,每条路有不满意程度和每减少一点不满意程度的花费,给出最大花费,要求找出花费小于s的最小生成树中最小的不满意程度
题解:首先明确的是肯定只删除一条路然后其他的找最小生成树即可,但是直接搞复杂度O(m*mlogm)所以先prim扣出一颗最小生成树,然后枚举所有边删这条边,如果在最小生成树上,直接减到贡献即可,如果不在最小生成树上,那么加上这条边,树肯定有环了,我们用lca暴力的扣出这个环最大的不满意程度的那条边,删掉即可,然后算贡献。总的复杂度是O(mlogm+m*logn)
//#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000009 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-12; const int N=200000+10,maxn=1000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; struct edge{ int u,v,id;ll w,c; bool operator <(const edge&rhs)const{ return w<rhs.w; } }e[N]; int father[N],fa[20][N],id[20][N],n,m,dep[N]; ll ma[20][N],s; bool vis[N]; vector<edge>v[N]; int Find(int x) { return father[x]==x?x:father[x]=Find(father[x]); } bool cmp(edge a,edge b) { return a.id<b.id; } ll prim() { for(int i=1;i<=m;i++)scanf("%lld",&e[i].w); for(int i=1;i<=m;i++)scanf("%lld",&e[i].c); for(int i=1;i<=m;i++) { e[i].id=i; scanf("%d%d",&e[i].u,&e[i].v); } for(int i=1;i<=n;i++)father[i]=i; sort(e+1,e+1+m); ll sum=0; for(int i=1;i<=m;i++) { int x=e[i].u,y=e[i].v; int fx=Find(x),fy=Find(y); if(fx!=fy) { father[fx]=fy; vis[e[i].id]=1; sum+=e[i].w; } } sort(e+1,e+1+m,cmp); for(int i=1;i<=m;i++) { if(vis[i]) { v[e[i].u].pb(e[i]); swap(e[i].u,e[i].v); v[e[i].u].pb(e[i]); } } return sum; } void dfs(int u,int f,int d) { dep[u]=d; for(int i=0;i<v[u].size();i++) { int x=v[u][i].v; if(x!=f) { fa[0][x]=u; ma[0][x]=v[u][i].w; id[0][x]=v[u][i].id; dfs(x,u,d+1); } } } void init() { dfs(1,-1,0); // for(int i=1;i<=n;i++)printf("%d %lld %d ",fa[0][i],ma[0][i],id[0][i]); for(int i=1;i<20;i++) { for(int j=1;j<=n;j++) { fa[i][j]=fa[i-1][fa[i-1][j]]; if(ma[i-1][fa[i-1][j]]>ma[i-1][j]) { ma[i][j]=ma[i-1][fa[i-1][j]]; id[i][j]=id[i-1][fa[i-1][j]]; } else { ma[i][j]=ma[i-1][j]; id[i][j]=id[i-1][j]; } } } } int lca(int x,int y) { if(dep[x]>dep[y])swap(x,y); int ans=0;ll maxx=0; for(int i=0;i<20;i++) { if((dep[y]-dep[x])>>i&1) { if(maxx<ma[i][y]) { maxx=ma[i][y]; ans=id[i][y]; } y=fa[i][y]; } } if(x==y)return ans; for(int i=19;i>=0;i--) { if(fa[i][x]!=fa[i][y]) { if(maxx<ma[i][x]) { maxx=ma[i][x]; ans=id[i][x]; } if(maxx<ma[i][y]) { maxx=ma[i][y]; ans=id[i][y]; } x=fa[i][x]; y=fa[i][y]; } } if(maxx<ma[0][x]) { maxx=ma[0][x]; ans=id[0][x]; } if(maxx<ma[0][y]) { maxx=ma[0][y]; ans=id[0][y]; } return ans; } void solve(ll sum) { ll ans=1e18,pos; for(int i=1;i<=m;i++) { if(vis[i]) { if(ans>sum-s/e[i].c) { ans=sum-s/e[i].c; pos=i; } } else { int ff=lca(e[i].u,e[i].v); if(ans>sum-e[ff].w+e[i].w-s/e[i].c) { ans=sum-e[ff].w+e[i].w-s/e[i].c; pos=i; } } } if(!vis[pos])vis[lca(e[pos].u,e[pos].v)]=0; printf("%lld ",ans); for(int i=1;i<=m;i++) { if(pos==i)printf("%d %d ",i,e[i].w-s/e[i].c); else if(vis[i])printf("%d %d ",i,e[i].w); } } int main() { scanf("%d%d",&n,&m); ll sum=prim(); scanf("%lld",&s); // for(int i=1;i<=n;i++) // { // for(int j=0;j<v[i].size();j++) // { // printf("%d %d %d %lld %lld ",v[i][j].u,v[i][j].v,v[i][j].id,v[i][j].w,v[i][j].c); // } // puts(""); // } init(); solve(sum); return 0; } /*********************** 3 3 1 1 1000 5 5 2 2 1 3 1 3 2 2 ***********************/