BZOJ2561 最小生成树(Dinic算法求最小割)
给定一个边带正权的连通无向图G=(V,E),其中N=|V|,M=|E|,N个点从1到N依次编号,给定三个正整数u,v,和L (u≠v),假设现在加入一条边权为L的边(u,v),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树上?
Input
第一行包含用空格隔开的两个整数,分别为N和M; 接下来M行,每行包含三个正整数u,v和w表示图G存在一条边权为w的边(u,v)。 最后一行包含用空格隔开的三个整数,分别为u,v,和 L; 数据保证图中没有自环。
Output
输出一行一个整数表示最少需要删掉的边的数量。
题解:
将所有比L小的边连一条边,计算最小割
重新建图,将所有比L大的边连一条边,计算最小割
两个值加起来就是答案。
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+10; const int inf=1e9; int N,M; struct node { int u; int v; int w; int next; }edge[maxn]; int head[maxn]; int tol=0; void addedge (int u,int v,int w) { edge[tol].u=u; edge[tol].v=v; edge[tol].w=w; edge[tol].next=head[u]; head[u]=tol++; } int dep[maxn]; int inque[maxn]; int vi; int cur[maxn]; int maxflow=0; int s,t; void init () { maxflow=0; vi=0; tol=0; memset(head,-1,sizeof(head)); } bool bfs () { for (int i=1;i<=N;i++) cur[i]=head[i],dep[i]=inf,inque[i]=0; dep[s]=0; queue<int> q; q.push(s); while (!q.empty()) { int u=q.front(); q.pop(); inque[u]=0; for (int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if (dep[v]>dep[u]+1&&edge[i].w) { dep[v]=dep[u]+1; if (inque[v]==0) { q.push(v); inque[v]=1; } } } } if (dep[t]!=inf) return 1; return 0; } int dfs (int u,int flow) { int increase=0; if (u==t) { vi=1; maxflow+=flow; return flow; } int used=0; for (int i=cur[u];i!=-1;i=edge[i].next) { cur[u]=i; int v=edge[i].v; if (edge[i].w&&dep[v]==dep[u]+1) { if (increase=dfs(v,min(flow-used,edge[i].w))) { used+=increase; edge[i].w-=increase; edge[i^1].w+=increase; if (used==flow) break; } } } return used; } int Dinic () { while (bfs()) { vi=1; while (vi==1) { vi=0; dfs(s,inf); } } return maxflow; } int a[maxn],b[maxn],c[maxn]; int main () { scanf("%d%d",&N,&M); for (int i=1;i<=M;i++) { scanf("%d%d%d",&a[i],&b[i],&c[i]); } int U,V,L; scanf("%d%d%d",&U,&V,&L); s=U; t=V; init(); int ans=0; for (int i=1;i<=M;i++) if (c[i]<L) { addedge(a[i],b[i],1); addedge(b[i],a[i],1); } ans+=Dinic(); init(); for (int i=1;i<=M;i++) if (c[i]>L) { addedge(a[i],b[i],1); addedge(b[i],a[i],1); } ans+=Dinic(); printf("%d\n",ans); return 0; }