这种出题人。。。。emmm。。。。一图以蔽之。
然后。。。。。
拖出去阿了
我嘞个去图论题你连条边都不给我让我怎么玩????这是我见过最牛逼的图论题了。。。
调了一个下午+一个晚上硬是调不出来,蛋疼。。。。
首先这道题肯定不会傻fufu的跑n^2次最小割,因为。。。算了直接开花。
但不用最小割。。。emmm。。。反正我也不会啊,所以就考虑减小最小割次数。
于是最小割树这种东东就出场了。。。。
想知道什么是最小割树的可参看这篇博客:传送门(肯定贴传送门啊因为我也懵啊)
这个东东有个性质:两点最小割等价于最小割树上两点路径最小值。
因为点数少,所以直接预处理所有点的最小割,O(n^2)回答询问即可。
至于预处理,则用到分治,不断将点集拆为两个更小的点集然后更新答案就行了。
#include
using namespace std;
const int MAXN=1e3+10;
const int MAXM=2e5+10;
const int INF=0x3f3f3f3f;
int n,m,cnt,s,t;
int cut[MAXN][MAXN],id[MAXN],tmp[MAXN];
int head[MAXN],cur[MAXN],d[MAXN];
int nxt[MAXM],to[MAXM],cap[MAXM],flow[MAXM];
int Read(){
int i=0,f=1;
char c;
for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
if(c=='-')
f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())
i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
void Add(int x,int y,int z){
nxt[cnt]=head[x];
head[x]=cnt;
to[cnt]=y;
cap[cnt]=z;
cnt++;
}
void add(int x,int y,int z){
Add(x,y,z);
Add(y,x,z);
}
int bfs(){
queue q;
memset(d,0,sizeof(d));
d[s]=1;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=nxt[i]){
int v=to[i];
if(!d[v]&&cap[i]>flow[i]){
d[v]=d[u]+1;
q.push(v);
}
}
}
return d[t];
}
int dfs(int u,int floww){
if(u==t||floww<=0)
return floww;
int res=0,di;
for(int &i=cur[u];i!=-1;i=nxt[i]){
int v=to[i];
if(d[v]==d[u]+1&&(di=dfs(v,min(floww,cap[i]-flow[i])))>0){
res+=di;
floww-=di;
flow[i]+=di;
flow[i^1]-=di;
if(floww<=0)
return res;
}
}
return res;
}
int dinic(){
int ret=0;
while(bfs()){
memcpy(cur,head,sizeof(head));
ret+=dfs(s,INF);
}
return ret;
}
void solve(int L,int R){
if(L==R)
return ;
memset(flow,0,sizeof(flow));
s=id[L],t=id[R];
int x=dinic();
int l=L,r=R;
for(int i=1;i<=n;++i){
if(d[i]){
for(int j=1;j<=n;++j){
if(!d[j])
cut[i][j]=cut[j][i]=min(cut[i][j],x);
}
}
}
for(int i=L;i<=R;++i){
tmp[d[id[i]]?l++:r--]=id[i];
}
for(int i=L;i<=R;++i){
id[i]=tmp[i];
}
solve(L,r),solve(l,R);
}
int main(){
int T=Read();
while(T--){
memset(head,-1,sizeof(head));
cnt=0;
n=Read(),m=Read();
for(int i=1;i<=m;++i){
int x=Read(),y=Read(),z=Read();
add(x,y,z);
}
for(int i=1;i<=n;++i)
id[i]=i;
memset(cut,INF,sizeof(cut));
solve(1,n);
int q=Read();
while(q--){
int x=Read();
int ans=0;
for(int i=1;i<=n;++i)
for(int j=i+1;j<=n;++j)
if(cut[i][j]<=x)
ans++;
cout<