- 和分治最小割那道题一样,多了一个建图的过程。
- 建出的图一定是一颗点数为
n的树。
- 查询直接
dfs,复杂度
5e7,开
O2过了qwq。其实可以写一下倍增,懒。
Coding
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=501;
const int M=1e4+10;
const int inf=1e9;
int n,m,Q,s,t,tot=1,ans,maxflow,flow,tc,ver[M],Next[M],lin[M],edge[M],yedge[M],d[N],vc[M],nc[M],lc[N],ec[M],v[N];
struct node{
int id,val;
}a[N];
int read(){
char ch=getchar();int num=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){num=(num<<1)+(num<<3)+(ch^48);ch=getchar();}
return num*f;
}
void add(int x,int y,int z){ver[++tot]=y;Next[tot]=lin[x];lin[x]=tot;edge[tot]=z;yedge[tot]=z;}
void addc(int x,int y,int z){vc[++tc]=y;nc[tc]=lc[x];lc[x]=tc;ec[tc]=z;}
bool cmp(node a,node b){return d[a.id]<d[b.id];}
bool bfs(){
queue<int>q;
memset(d,0,sizeof(d));
d[s]=1,q.push(s);
while(q.size()){
int x=q.front();q.pop();
for(int i=lin[x];i;i=Next[i]){
int y=ver[i];
if(!d[y]&&edge[i]){
d[y]=d[x]+1;q.push(y);
if(y==t) return 1;
}
}
}return 0;
}
int dinic(int x,int flow){
if(x==t) return flow;
int rest=flow;
for(int i=lin[x];i&&rest;i=Next[i]){
int y=ver[i];
if(d[y]==d[x]+1&&edge[i]){
int k=dinic(y,min(edge[i],rest));
if(!k) d[y]=0;
rest-=k,edge[i]-=k,edge[i^1]+=k;
if(!rest) return flow-rest;
}
}return flow-rest;
}
void CDQ(int l,int r){
if(l==r) return;
s=a[l].id,t=a[r].id;
maxflow=flow=0;
for(int i=2;i<=tot;++i) edge[i]=yedge[i];
while(bfs()){
while(flow=dinic(s,inf)) maxflow+=flow;
}
addc(s,t,maxflow);addc(t,s,maxflow);
sort(a+l,a+r+1,cmp);
int mid;
for(int i=l;i<=r;++i) if(d[a[i].id]>0){mid=i-1;break;}
CDQ(l,mid);CDQ(mid+1,r);
}
void dfs(int x,int now,int temp){
v[x]=1;
if(x==now){
ans=temp;return;
}
for(int i=lc[x];i;i=nc[i]){
int y=vc[i];
if(v[y]) continue;
dfs(y,now,min(temp,ec[i]));
}
}
int main(){
n=read(),m=read();
for(int i=1;i<=m;++i){
int x=read(),y=read(),z=read();
add(x,y,z);add(y,x,z);
}
for(int i=0;i<=n;++i) a[i].id=i;
CDQ(0,n);
Q=read();
while(Q--){
int x=read(),y=read();
ans=1e9;for(int i=0;i<=n;++i) v[i]=0;
dfs(x,y,1e9);
printf("%d\n",ans);
}
return 0;
}