冷门知识点……
原题:
小白在图论课上学到了一个新的概念——最小割,下课后小白在笔记本上写下了如下这段话: “对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割。 对于带权图来说,将所有顶点处在不同部分的边的权值相加所得到的值定义为这个割的容量,而s,t的最小割指的是在关于s,t的割中容量最小的割” 现给定一张无向图,小白有若干个形如“图中有多少对点它们的最小割的容量不超过x呢”的疑问,小蓝虽然很想回答这些问题,但小蓝最近忙着挖木块,于是作为仍然是小蓝的好友,你又有任务了。
1<=u,v<=n,0<=c<=106
分治最小割:O(跑得过)时间处理n个点两两之间的最小割
每次在当前集合中随意找两个点,最小割成两个集合,递归处理这两个集合,开O(n^2)数组记录答案
注意初始化
没了
(注意"两组测试数据之间用空行隔开",否则PE)
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int oo=;
int rd(){int z=,mk=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')mk=-; ch=getchar();}
while(ch>=''&&ch<=''){z=(z<<)+(z<<)+ch-''; ch=getchar();}
return z*mk;
}
struct ddd{int nxt,y,v,rvs;}e[]; int lk[],ltp=;
inline void ist(int x,int y,int z){
e[++ltp].nxt=lk[x],lk[x]=ltp,e[ltp].y=y,e[ltp].v=z,e[ltp].rvs=ltp+;
e[++ltp].nxt=lk[y],lk[y]=ltp,e[ltp].y=x,e[ltp].v=z,e[ltp].rvs=ltp-;
}
int n,m,qst; int s,t;
int lvl[];
int q[],hd=;
bool st[];
int quq[],tmp[];
int mnct[][];
bool gtlvl(){
memset(lvl,,sizeof(lvl));
q[hd=]=s,lvl[s]=;
for(int k=;k<=hd;++k)
for(int i=lk[q[k]];i;i=e[i].nxt)if(e[i].v && !lvl[e[i].y])
lvl[e[i].y]=lvl[q[k]]+,q[++hd]=e[i].y;
return lvl[t];
}
int mxflw(int x,int y){
if(x==t) return y;
int bwl=,flw=;
for(int i=lk[x];i && bwl<y;i=e[i].nxt)if(e[i].v && lvl[e[i].y]==lvl[x]+)
if((flw=mxflw(e[i].y,min(y-bwl,e[i].v)))){
bwl+=flw;
e[i].v-=flw,e[e[i].rvs].v+=flw;
}
if(!bwl) lvl[x]=;
return bwl;
}
void gtst(){
q[hd=]=s,st[s]=true;
for(int k=;k<=hd;++k)for(int i=lk[q[k]];i;i=e[i].nxt)
if(e[i].v && !st[e[i].y]) st[e[i].y]=true,q[++hd]=e[i].y;
}
int dnc(){
int bwl=,flw=;
while(gtlvl())while((flw=mxflw(s,oo))) bwl+=flw;
memset(st,,sizeof(st));
gtst();
return bwl;
}
void sprt(int l,int r){
if(l>=r) return ;
for(int i=;i<=ltp;++i) e[i].v=e[e[i].rvs].v=(e[i].v+e[e[i].rvs].v)>>;
s=quq[l],t=quq[r];
int mxflw=dnc();
for(int i=;i<=n;++i)if(st[i])for(int j=;j<=n;++j)if(!st[j])
mnct[j][i]=mnct[i][j]=min(mnct[i][j],mxflw);
int hd1=l,hd2=r;
for(int i=l;i<=r;++i) tmp[(st[quq[i]] ? hd2-- : hd1++)]=quq[i];
for(int i=l;i<=r;++i) quq[i]=tmp[i];
sprt(l,hd1-),sprt(hd2+,r);
}
void clr(){ memset(lk,,sizeof(lk)),ltp=; memset(mnct,,sizeof(mnct));}
int main(){//freopen("ddd.in","r",stdin);
int T; cin>>T; while(T--){ clr();
cin>>n>>m;
for(int i=;i<=n;++i) quq[i]=i;
int l,r,v,cnt=;
while(m--) l=rd(),r=rd(),v=rd(),ist(l,r,v);
sprt(,n);
cin>>qst;
while(qst--){
v=rd(),cnt=;
for(int i=;i<=n;++i)for(int j=i+;j<=n;++j)if(mnct[i][j]<=v) ++cnt;
printf("%d\n",cnt);
}
cout<<endl;
continue;
}
return ;
}