题解 点点的最大流
思路还是比较容易想到的,缩点后树剖即可
复杂度是两个 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;
}