把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P4412 [SHOI2004]最小生成树

题面传送门
首先这个在树上的边肯定只是变小,不在树上的边肯定只是增大。
我们设在树上的一条边为\(e\),边权和变化量为\(W_e\)\(deta_e\),与这条边构成环的非树边为\(e'\)
那么肯定有\(W_e-deta_e\leq W_{e'}+deta_{e'}\)
移项以后是\(W_e-W_{e'}\leq deta_e+deta_{e'}\)
左边看成边权,右边看成顶标,那么就是KM直接上。
时间复杂度\(O(m^3)\)但是根本不像。
谁家\(m=1500\)\(O(m^3)\)\(12ms\)啊!
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define lb long db
#define N 50
#define M 800
#define mod 998244353
#define Mod 998244352
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n,m,k,x[M+5],y[M+5],z[M+5],A[N+5][N+5],Fl[N+5][N+5],d[N+5],Id[N+5],W[N+5][N+5],a,b,fa[N+5];
struct yyy{int to,w,z;};
struct ljb{int head,h[N+5];yyy f[N+5<<1];I void add(int x,int y,int z){f[++head]=(yyy){y,z,h[x]};h[x]=head;}}s;
I void Make(int x,int last){fa[x]=last;d[x]=d[last]+1;yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&(Make(tmp.to,x),Id[tmp.to]=tmp.w);}
struct KM{
	int px[M+5],py[M+5],pre[M+5],W[M+5][M+5],vx[M+5],vy[M+5],slack[M+5],lx[M+5],ly[M+5],ToT;queue<int> Q;
 	I void insert(int x,int y,int z){W[x][y]=max(z,W[x][y]);lx[x]=max(lx[x],z);}I void aug(int x){while(x) py[x]=pre[x],swap(x,px[pre[x]]);}
	I void bfs(int x){
		re int i;while(!Q.empty()) Q.pop();Me(slack,0x3f);Me(vx,0);Me(vy,0);Q.push(x);while(1){while(!Q.empty()){
			     x=Q.front();Q.pop();vx[x]=1;for(i=1;i<=m;i++){if(vy[i]||slack[i]<=lx[x]+ly[i]-W[x][i])continue;slack[i]=lx[x]+ly[i]-W[x][i];pre[i]=x;if(!slack[i]){vy[i]=1;if(!py[i])return aug(i);Q.push(py[i]);}} 
		    }for(ToT=1e9,i=1;i<=m;i++) !vy[i]&&(ToT=min(ToT,slack[i]));for(i=1;i<=m;i++) vx[i]&&(lx[i]-=ToT),vy[i]?(ly[i]+=ToT):(slack[i]-=ToT);for(i=1;i<=m;i++) if(!slack[i]&&!vy[i]){vy[i]=1;if(!py[i]) return aug(i);Q.push(py[i]);}
		}
	}
	I int GetAns(){re int i;for(i=1;i<=m;i++) bfs(i);for(ToT=0,i=1;i<=m;i++) ToT+=lx[i]+ly[i];return ToT;}
}T;
I void insert(int x,int y,int id){d[x]<d[y]&&(swap(x,y),0);while(d[x]^d[y]) T.insert(Id[x],id,z[Id[x]]-z[id]),x=fa[x];while(x^y) T.insert(Id[x],id,z[Id[x]]-z[id]),T.insert(Id[y],id,z[Id[y]]-z[id]),x=fa[x],y=fa[y];}
int main(){
	freopen("1.in","r",stdin);
	re int i;scanf("%d%d",&n,&m);for(i=1;i<=m;i++) scanf("%d%d%d",&x[i],&y[i],&z[i]),W[x[i]][y[i]]=W[y[i]][x[i]]=i;for(i=1;i<n;i++) scanf("%d%d",&a,&b),Fl[a][b]=Fl[b][a]=1,s.add(b,a,W[b][a]),s.add(a,b,W[a][b]);
	Make(1,0);for(i=1;i<=m;i++) !Fl[x[i]][y[i]]&&(insert(x[i],y[i],i),0);printf("%d\n",T.GetAns());
}
posted @ 2021-08-17 18:18  275307894a  阅读(38)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end