题解 [SHOI2010]最小生成树

 题面

解析

看上去是黑题啊!

实际上也就是道网络流最大流。

当然,我们也知道网络流最关键的是建图。

首先,分析一下题目:

题目要求在操作后使给定的边lab一定在最小生成树上,

求最小的操作数。

先设lab连通的边为A,B。

那么,根据Krustal算法,在加入lab时一定没有权值比lab小的边使A,B连通。

所以,只要将权值比lab小的边重新建图,

将容量设为这条边最少的操作次数就行了。

而最小的操作次数就应该是wlab −wi +1。

最后求A到B的最小割(最大流)就行了。

上AC代码:

#include<bits/stdc++.h>
using namespace std;

inline int read(){
    int sum=0,f=1;char ch=getchar();
    while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    return f*sum;
}


const int INF=0x3f3f3f3f;
struct road{
    int next,to,w;
}e[100001];
struct line{
    int x,y,w;
}a[100001];
int n,m,lab;
int s,t;
int head[10001],cnt=1;
int d[100001],v[100001];

void add(int x,int y,int w){
    e[++cnt].to=head[x];
    e[cnt].next=y;
    e[cnt].w=w;
    head[x]=cnt;
}

bool bfs(){
    memset(d,-1,sizeof(d));
    memset(v,0,sizeof(v));
    queue <int> que;
    que.push(s);
    v[s]=1;
    d[s]=1;
    while(!que.empty()){
        int x=que.front();
        que.pop();
        for(int i=head[x];i;i=e[i].to){
            int k=e[i].next;
            if(v[k]||!e[i].w) continue;
            v[k]=1;
            d[k]=d[x]+1;            
            que.push(k);
        }
    }
    if(d[t]>0) return 1;
    return 0;
}

int dfs(int x,int low){
    if(x==t) return low;
    int c=0;
    for(int i=head[x];i;i=e[i].to){
        int k=e[i].next;
        if(d[k]!=d[x]+1) continue;
        if(!e[i].w) continue;
        if((c=dfs(k,min(low,e[i].w)))){
            e[i].w-=c;
            e[i^1].w+=c;
            return c;
        }
    }
    return 0;
}

void DINIC(){
    int ans=0,mi;
    while(bfs()){
        while((mi=dfs(s,INF))) ans+=mi;
    }
    printf("%d\n",ans);
    return ;
}

int main(){
//    freopen("mst.in","r",stdin);
//    freopen("mst.out","w",stdout);
    n=read();m=read();lab=read();
    for(int i=1;i<=m;i++){
        a[i].x=read();a[i].y=read();a[i].w=read();
    }
    s=a[lab].x;t=a[lab].y;
    for(int i=1;i<=m;i++){
        if(a[i].w<=a[lab].w&&i!=lab){
            add(a[i].x,a[i].y,a[lab].w-a[i].w+1);
            add(a[i].y,a[i].x,0);
            add(a[i].y,a[i].x,a[lab].w-a[i].w+1);
            add(a[i].x,a[i].y,0);            
        }
    }
    DINIC();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zsq259/p/10502130.html
今日推荐