题解 点点的最大流

传送门

思路还是比较容易想到的,缩点后树剖即可
复杂度是两个 log
但代码实现比较阴间
其实貌似还可以用 lct 写但是我不会

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
#define N 600010
#define ll long long
#define fir first
#define sec second
#define pb push_back
//#define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m, q;
int head[N], size=1;
struct edge{int from, to, next; ll val;}e[N<<1];
inline void add(int s, int t, ll w) {e[++size]={s, t, head[s], w}; head[s]=size;}

namespace force{
	pair<int, int> rel[N];
	int dep[N], cur[N], s, t;
	bool bfs(int s, int t) {
		memset(dep, 0, sizeof(dep));
		queue<int> q;
		dep[s]=1; q.push(s);
		cur[s]=head[s];
		int u;
		while (q.size()) {
			u=q.front(); q.pop();
			for (int i=head[u],v; ~i; i=e[i].next) {
				v = e[i].to;
				if (e[i].val&&!dep[v]) {
					dep[v]=dep[u]+1;
					cur[v]=head[v];
					if (v==t) return 1;
					q.push(v);
				}
			}
		}
		return 0;
	}
	ll dfs(int u, ll in) {
		if (u==t||!in) return in;
		ll rest=in, tem;
		for (int i=cur[u],v; ~i; cur[u]=i=e[i].next) {
			v = e[i].to;
			if (e[i].val&&dep[v]==dep[u]+1) {
				tem=dfs(v, min(rest, e[i].val));
				if (!tem) dep[v]=0;
				rest-=tem;
				e[i].val-=tem;
				e[i^1].val+=tem;
				if (!rest) break;
			}
		}
		return in-rest;
	}
	ll dinic() {
		ll ans=0;
		for (int i=2; i<=size; i+=2) e[i].val+=e[i^1].val, e[i^1].val=0;
		while (bfs(s, t)) ans+=dfs(s, INF);
		return ans;
	}
	void solve() {
		for (int i=1,u,v,w; i<=m; ++i) {
			u=read(); v=read(); w=read();
			rel[i]={size+1, size+3};
			add(u, v, w), add(v, u, 0);
			add(v, u, w), add(u, v, 0);
		}
		q=read();
		for (int i=1,x,f; i<=q; ++i) {
			if (read()&1) {
				x=read(); f=read();
				e[rel[x].fir].val=f, e[rel[x].fir^1].val=0;
				e[rel[x].sec].val=f, e[rel[x].sec^1].val=0;
			}
			else {
				s=read(); t=read();
				printf("%lld\n", dinic());
			}
		}
	}
}

namespace task1{
	int dep[N], back[N], top[N], id[N], rk[N], siz[N], msiz[N], mson[N], val[N], tot;
	int tl[N<<2], tr[N<<2]; ll dat[N<<2];
	#define tl(p) tl[p]
	#define tr(p) tr[p]
	#define dat(p) dat[p]
	#define pushup(p) dat(p)=min(dat(p<<1), dat(p<<1|1))
	void build(int p, int l, int r) {
		tl(p)=l; tr(p)=r;
		if (l==r) {dat(p)=val[rk[l]]; return ;}
		int mid=(l+r)>>1;
		build(p<<1, l, mid);
		build(p<<1|1, mid+1, r);
		pushup(p);
	}
	void upd(int p, int pos, ll val) {
		if (tl(p)==tr(p)) {dat(p)=val; return ;}
		int mid=(tl(p)+tr(p))>>1;
		if (pos<=mid) upd(p<<1, pos, val);
		else upd(p<<1|1, pos, val);
		pushup(p);
	}
	ll query(int p, int l, int r) {
		if (l<=tl(p)&&r>=tr(p)) return dat(p);
		int mid=(tl(p)+tr(p))>>1; ll ans=INF;
		if (l<=mid) ans=min(ans, query(p<<1, l, r));
		if (r>mid) ans=min(ans, query(p<<1|1, l, r));
		return ans;
	}
	void dfs1(int u, int pa) {
		siz[u]=1;
		for (int i=head[u],v; ~i; i=e[i].next) {
			v = e[i].to;
			if (v==pa) {val[u]=e[i].val; continue;}
			dep[v]=dep[u]+1; back[v]=u;
			dfs1(v, u);
			siz[u]+=siz[v];
			if (siz[v]>msiz[u]) msiz[u]=siz[v], mson[u]=v;
		}
	}
	void dfs2(int u, int fa, int t) {
		id[u]=++tot;
		rk[tot]=u;
		top[u]=t;
		if (!mson[u]) return ;
		dfs2(mson[u], u, t);
		for (int i=head[u],v; ~i; i=e[i].next) {
			v = e[i].to;
			if (v==fa||v==mson[u]) continue;
			dfs2(v, u, v);
		}
	}
	ll qmin(int a, int b) {
		ll ans=INF;
		while (top[a]!=top[b]) {
			if (dep[top[a]]<dep[top[b]]) swap(a, b);
			ans=min(ans, query(1, id[top[a]], id[a]));
			a=back[top[a]];
		}
		if (dep[a]>dep[b]) swap(a, b);
		if (a!=b) ans=min(ans, query(1, id[a]+1, id[b]));
		return ans;
	}
	void solve() {
		for (int i=1,u,v,w; i<=m; ++i) {
			u=read(); v=read(); w=read();
			add(u, v, w), add(v, u, w);
		}
		dfs1(1, 0); dfs2(1, 0, 1); build(1, 1, n);
		q=read();
		for (int i=1,s,t,x,f; i<=q; ++i) {
			if (read()&1) {
				x=read(); f=read();
				s=e[x<<1].from, t=e[x<<1].to;
				if (dep[s]<dep[t]) swap(s, t);
				val[s]=f;
				upd(1, id[s], f);
			}
			else {
				s=read(); t=read();
				printf("%lld\n", qmin(s, t));
			}
		}
	}
}

namespace task{
	bool cut[N], inring[N], vis[N];
	pair<int, int> eid[N];
	vector<int> s1[N], s2[N];
	ll val1[N], val2[N], tem[N];
	int siz[N], dep[N], back[N], msiz[N], mson[N], id[N], rk[N], top[N], idcnt;
	int dsu[N], sta[N], dfn[N], low[N], pos1[N], pos2[N], dlt[N], out[N], out_to[N], tot, pos;
	inline int find(int p) {return dsu[p]==p?p:dsu[p]=find(dsu[p]);}
	namespace edge2{
		int head[N], size;
		struct edge{int to, next, s, t; ll val;}e[N<<1];
		inline void add(int s, int t, int ss, int tt, ll w) {e[++size]={t, head[s], ss, tt, w}; head[s]=size;}
	}
	struct seg{
		int tl[N<<2], tr[N<<2]; ll dat[N<<2];
		void build(int p, int l, int r, ll* val) {
			tl(p)=l; tr(p)=r;
			if (l==r) {dat(p)=val[rk[l]]; return ;}
			int mid=(l+r)>>1;
			build(p<<1, l, mid, val);
			build(p<<1|1, mid+1, r, val);
			pushup(p);
		}
		void upd(int p, int pos, ll val) {
			if (tl(p)==tr(p)) {dat(p)=val; return ;}
			int mid=(tl(p)+tr(p))>>1;
			if (pos<=mid) upd(p<<1, pos, val);
			else upd(p<<1|1, pos, val);
			pushup(p);
		}
		ll query(int p, int l, int r) {
			if (l<=tl(p)&&r>=tr(p)) return dat(p);
			int mid=(tl(p)+tr(p))>>1; ll ans=INF;
			if (l<=mid) ans=min(ans, query(p<<1, l, r));
			if (r>mid) ans=min(ans, query(p<<1|1, l, r));
			return ans;
		}
	}seg1, seg2, seg3;
	void tarjan(int u, int in_edge) {
		// cout<<"tarjan: "<<u<<' '<<in_edge<<endl;
		in_edge^=1;
		dfn[u]=low[u]=++tot;
		for (int i=head[u],v; ~i; i=e[i].next) {
			v = e[i].to;
			if (!dfn[v]) {
				tarjan(v, i);
				if (low[v]>dfn[u]) cut[i]=cut[i^1]=1;
				low[u]=min(low[u], low[v]);
			}
			else if (i!=in_edge) low[u]=min(low[u], dfn[v]);
		}
	}
	void dfs3(int u, vector<int>& s1, vector<int>& s2, int in_edge) {
		vis[u]=1; s1.pb(u); s2.pb(in_edge);
		for (int i=head[u],v; ~i; i=e[i].next) if (!cut[i]) {
			v = e[i].to;
			if (vis[v]) {s2[0]=i; continue;}
			dfs3(v, s1, s2, i);
		}
	}
	ll qval(int s, int t) {
		// cout<<"qval: "<<s<<' '<<t<<endl;
		assert(find(s)==find(t));
		int u=find(s);
		if (pos1[s]>pos1[t]) swap(s, t);
		// cout<<"query: "<<dlt[u]+pos1[s]+2<<' '<<dlt[u]+pos1[t]+1<<' '<<dlt[u]+pos1[t]+2<<' '<<dlt[u]+pos2[s]+1<<endl;
		return seg3.query(1, dlt[u]+pos1[s]+2, dlt[u]+pos1[t]+1)+seg3.query(1, dlt[u]+pos1[t]+2, dlt[u]+pos2[s]+1);
	}
	void dfs1(int u, int pa) {
		using namespace edge2;
		siz[u]=1;
		for (int i=head[u],v; ~i; i=e[i].next) {
			v = e[i].to;
			if (v==pa) {val1[u]=e[i].val; out[u]=e[i].s; out_to[u]=e[i].t; continue;}
			dep[v]=dep[u]+1; back[v]=u;
			dfs1(v, u);
			siz[u]+=siz[v];
			if (siz[v]>msiz[u]) msiz[u]=siz[v], mson[u]=v;
		}
	}
	void dfs2(int u, int fa, int t) {
		// cout<<"dfs2: "<<u<<' '<<fa<<' '<<t<<endl;
		using namespace edge2;
		id[u]=++idcnt;
		rk[idcnt]=u;
		top[u]=t;
		val2[u]=INF;
		if (!mson[u]) return ;
		if (fa) val2[u]=qval(out_to[mson[u]], out[u]);
		else val2[u]=INF, out[u]=1;
		dfs2(mson[u], u, t);
		for (int i=head[u],v; ~i; i=e[i].next) {
			v = e[i].to;
			if (v==fa||v==mson[u]) continue;
			dfs2(v, u, v);
		}
	}
	int lca(int a, int b) {
		while (top[a]!=top[b]) {
			if (dep[top[a]]<dep[top[b]]) swap(a, b);
			a=back[top[a]];
		}
		if (dep[a]>dep[b]) swap(a, b);
		return a;
	}
	ll qmin(int a, int b) {
		// cout<<"qmin: "<<a<<' '<<b<<endl;
		ll ans=INF;
		int ta=a, tb=b, sta[3], stop=0;
		if (find(a)==find(b)) return qval(a, b);
		int t=lca(find(a), find(b)); //, in_lca=-1;
		ans=min(ans, min(find(a)==t?INF:qval(a, out[find(a)]), find(b)==t?INF:qval(b, out[find(b)])));
		// cout<<out[find(a)]<<endl;
		// cout<<"ans: "<<ans<<endl;
		a=find(a), b=find(b);
		// if (a==t||b==t) in_lca=(a==t?ta:tb);
		if (a==t||b==t) sta[++stop]=(a==t?ta:tb);
		// cout<<"lca: "<<t<<' '<<a<<' '<<b<<endl;
		while (top[a]!=top[b]) {
			if (dep[top[a]]<dep[top[b]]) swap(a, b);
			// cout<<"ab: "<<a<<' '<<b<<endl;
			ans=min(ans, seg1.query(1, id[top[a]], id[a]));
			if (id[top[a]]<id[a]) ans=min(ans, seg2.query(1, id[top[a]], id[a]-1));
			if (back[top[a]]!=t) ans=min(ans, qval(out_to[top[a]], out[back[top[a]]]));
			// else if (in_lca==-1) in_lca=out_to[top[a]];
			else sta[++stop]=out_to[top[a]];
			a=back[top[a]];
		}
		// cout<<a<<' '<<endl;
		// cout<<"in_lca: "<<in_lca<<endl;
		if (dep[a]>dep[b]) swap(a, b);
		if (a!=b) ans=min(ans, seg1.query(1, id[a]+1, id[b]));
		if (id[a]+1<id[b]) ans=min(ans, seg2.query(1, id[a]+1, id[b]-1));
		// cout<<rk[id[a]]<<endl;
		// cout<<"son: "<<out_to[rk[id[a]+1]]<<endl;
		// ans=min(ans, qval(out_to[rk[id[a]+1]], in_lca));
		if (stop==2) ans=min(ans, qval(sta[1], sta[2]));
		else ans=min(ans, qval(out_to[rk[id[a]+1]], sta[1]));
		return ans;
	}
	void solve() {
		memset(edge2::head, -1, sizeof(edge2::head));
		for (int i=1,u,v,w; i<=m; ++i) {
			u=read(); v=read(); w=read();
			add(u, v, w), add(v, u, w);
		}
		for (int i=1; i<=n; ++i) dsu[i]=i;
		tarjan(1, 0);
		// cout<<"cut: "; for (int i=2; i<=size; ++i) cout<<cut[i]<<' '; cout<<endl;
		seg3.build(1, 1, n*3, tem);
		for (int i=1; i<=n; ++i) if (!vis[i]) {
			dfs3(i, s1[i], s2[i], 0);
			dlt[i]=pos;
			// cout<<"ring: "; for (auto it:s1[i]) cout<<it<<' '; cout<<endl;
			for (int j=0,end=s1[i].size(); j<end; ++j) {
				s1[i].pb(s1[i][j]);
				pos1[s1[i][j]]=j, pos2[s1[i][j]]=j+end;
				if (s1[i][j]!=i) dsu[find(s1[i][j])]=find(i);
			}
			// cout<<"s1: "; for (auto it:s1[i]) cout<<it<<' '; cout<<endl;
			for (int j=0,end=s2[i].size(); j<end; ++j) {
				s2[i].pb(s2[i][j]); inring[s2[i][j]>>1]=1;
				eid[s2[i][j]>>1]={pos+1+j, pos+1+j+end};
				// cout<<"upd3: "<<pos+1+j<<' '<<e[s2[i][j]].val<<endl;
				// cout<<"upd3: "<<pos+1+j+end<<' '<<e[s2[i][j]].val<<endl;
				seg3.upd(1, pos+1+j, e[s2[i][j]].val);
				seg3.upd(1, pos+1+j+end, e[s2[i][j]].val);
			}
			// cout<<"s2: "; for (auto it:s2[i]) cout<<e[it].val<<' '; cout<<endl;
			pos+=s2[i].size();
		}
		for (int i=2,s,t; i<=size; ++i) {
			s=e[i].from, t=e[i].to;
			if (find(s)==find(t)) continue;
			edge2::add(find(s), find(t), s, t, e[i].val);
		}
		// cout<<"bel: "; for (int i=1; i<=n; ++i) cout<<find(i)<<' '; cout<<endl;
		dfs1(find(1), 0);
		dfs2(find(1), 0, find(1));
		// cout<<"val1: "; for (int i=1; i<=n; ++i) cout<<val1[i]<<' '; cout<<endl;
		// cout<<"val2: "; for (int i=1; i<=n; ++i) cout<<val2[i]<<' '; cout<<endl;
		// cout<<"out: "; for (int i=1; i<=n; ++i) cout<<out[i]<<' '; cout<<endl;
		// cout<<"out_to: "; for (int i=1; i<=n; ++i) cout<<out_to[i]<<' '; cout<<endl;
		seg1.build(1, 1, idcnt, val1); seg2.build(1, 1, idcnt, val2);

		q=read();
		int cnt=0;
		for (int i=1,s,t,x,f; i<=q; ++i) {
			// cout<<"i: "<<i<<endl;
			if (read()&1) {
				x=read(); f=read();
				s=find(e[x<<1].from), t=find(e[x<<1].to);
				e[x<<1].val=f; e[x<<1|1].val=f;
				if (dep[s]<dep[t]) swap(s, t);
				if (inring[x]) {
					// cout<<"pos1"<<endl;
					seg3.upd(1, eid[x].fir, f);
					seg3.upd(1, eid[x].sec, f);
					// cout<<"s: "<<s<<' '<<t<<endl;
					if (back[s]&&mson[s]) seg2.upd(1, id[s], qval(out_to[mson[s]], out[s])); //, cout<<1<<endl;
				}
				else {
					// cout<<"pos2"<<endl;
					val1[s]=f;
					seg1.upd(1, id[s], f);
				}
			}
			else {
				s=read(); t=read();
				// ++cnt;
				// if (cnt==488) {
				// 	cout<<s<<' '<<t<<' '<<find(s)<<' '<<find(t)<<endl;
				// 	for (int i=1; i<=m; ++i) cout<<e[i<<1].from<<' '<<e[i<<1].to<<' '<<e[i<<1].val<<endl;
				// 	exit(0);
				// }
				printf("%lld\n", qmin(s, t));
			}
		}
	}
}

signed main()
{
	n=read(); m=read();
	memset(head, -1, sizeof(head));
	// if (m==n-1) task1::solve();
	// else force::solve();
	task::solve();

	return 0;
}
posted @ 2022-01-19 06:52  Administrator-09  阅读(0)  评论(0编辑  收藏  举报