Bzoj2229:[Zjoi2011]最小割:分治最小割

来源:互联网 发布:手机sql注入 编辑:程序博客网 时间:2024/05/18 04:59

题目链接2229:[Zjoi2011]最小割

分治最小割裸题

注意dinic时各种标记数组要全部完全地初始化,并不只是当前的S->T

#include<queue>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#define LL intusing namespace std;const int maxn=155;const int inf=0x7fffffff/2-1;int n,m,tot,h[maxn];struct edge{int to,next;LL w;}G[maxn*100];int S,T,cur[maxn],a[maxn],tmp[maxn];int vis[maxn];bool flag[maxn];LL ans[maxn][maxn];void add(int x,int y,LL z){G[++tot].to=y;G[tot].next=h[x];h[x]=tot;G[tot].w=z;}bool bfs(){for (int i=0;i<=n;++i) vis[i]=-1;queue<int>q; q.push(S); vis[S]=0;while (!q.empty()){int u=q.front(); q.pop();for (int i=h[u];i;i=G[i].next){int v=G[i].to;if (vis[v]==-1&&G[i].w){vis[v]=vis[u]+1;q.push(v);}}}return vis[T]!=-1;}int dfs(int x,LL f){if (x==T||f==0) return f;LL w,used=0;for (int i=cur[x];i;i=G[i].next)    if (vis[G[i].to]==vis[x]+1){w=f-used;w=dfs(G[i].to,min(w,G[i].w));G[i].w-=w; G[i^1].w+=w;used+=w; if (G[i].w) cur[x]=i;if (used==f) return used;    }if (!used) vis[x]=-1;return used;}void dfs_f(int x){flag[x]=1;for (int i=h[x];i;i=G[i].next)    if (!flag[G[i].to]&&G[i].w)        dfs_f(G[i].to);}void get_his(){for (int i=2;i<=tot;i+=2)    G[i].w=G[i^1].w=((G[i].w+G[i^1].w)>>1);}void solve(int l,int r){if (l==r) return;get_his(); S=a[l]; T=a[r];int ret=0;while (bfs()){for (int i=1;i<=n;++i) cur[i]=h[i];ret+=dfs(S,inf);}memset(flag,0,sizeof(flag));dfs_f(S);for (int i=1;i<=n;++i)    if (flag[i])        for (int j=1;j<=n;++j)            if (!flag[j])ans[i][j]=ans[j][i]=min(ans[i][j],ret);int L=l,R=r;for (int i=l;i<=r;++i)    if (flag[a[i]]) tmp[L++]=a[i];else tmp[R--]=a[i];for (int i=l;i<=r;++i) a[i]=tmp[i];solve(l,L-1); solve(R+1,r);}int main(){int T; scanf("%d",&T);while (T--){memset(h,0,sizeof(h)); tot=1;memset(ans,127,sizeof(ans));scanf("%d%d",&n,&m);for (int i=1;i<=m;++i){int x,y,z;scanf("%d%d%d",&x,&y,&z);add(x,y,z); add(y,x,z);}for (int i=1;i<=n;++i) a[i]=i;solve(1,n);int q; scanf("%d",&q);for (int i=1;i<=q;++i){int prt=0,x;scanf("%d",&x);for (int i=1;i<=n;++i)    for (int j=i+1;j<=n;++j)if(ans[i][j]<=x)prt++;printf("%d\n",prt);}printf("\n");}}




3 0
原创粉丝点击