BZOJ2561 最小生成树(Dinic算法求最小割)

Description

 给定一个边带正权的连通无向图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;
}

猜你喜欢

转载自www.cnblogs.com/zhanglichen/p/12509272.html