zoukankan      html  css  js  c++  java
  • [SHOI2010]最小生成树

    题目

    首先让其余所有边都减(1)和让自己加(1)没什么区别

    考虑(kruskal)的过程

    首先边权大于这条边的是不用考虑的

    考虑把那些边权比这条边小的调节到比这条边大,这样就相当于在生成树上去掉了这条边(被这条边取代了)

    至于调大到多少自然是使得边权恰好大(1)

    让这条边必然存在就一定得让这条边链接的两个点不连通,于是我们把在生成树上去掉这条边看成割断这条边,于是这就是一个最小割

    代码

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    const int maxn=1005;
    const int inf=999999999;
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    std::queue<int> q;
    struct E{int v,nxt,f;}e[maxn*4];
    struct Ed{int u,v,w,o;}E[maxn];
    inline int cmp(Ed A,Ed B) {if(A.w==B.w) return A.o<B.o;return A.w<B.w;}
    int num=1,n,m,S,T,lb;
    int head[maxn],d[maxn],cur[maxn];
    inline void C(int x,int y,int f) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].f=f;}
    inline void add(int x,int y,int f) {C(x,y,f),C(y,x,0);}
    inline int BFS() {
        for(re int i=1;i<=n;i++) d[i]=0,cur[i]=head[i];
        q.push(S),d[S]=1;
        while(!q.empty()) {
            int k=q.front();q.pop();
            for(re int i=head[k];i;i=e[i].nxt)
            if(!d[e[i].v]&&e[i].f) d[e[i].v]=d[k]+1,q.push(e[i].v);
        }
        return d[T];
    }
    int dfs(int x,int now) {
        if(x==T||!now) return now;
        int flow=0,ff;
        for(re int& i=cur[x];i;i=e[i].nxt)
        if(d[e[i].v]==d[x]+1) {
            ff=dfs(e[i].v,min(now,e[i].f));
            if(ff<=0) continue;
            now-=ff,flow+=ff,e[i].f-=ff,e[i^1].f+=ff;
            if(!now) break;
        }
        return flow;
    }
    int main() {
    	n=read(),m=read(),lb=read();
    	for(re int i=1;i<=m;i++) E[i].u=read(),E[i].v=read(),E[i].w=read();
    	E[lb].o=1;int t=E[lb].w;
    	S=E[lb].u,T=E[lb].v;
    	std::sort(E+1,E+m+1,cmp);
    	for(re int i=1;i<=m;i++){
    		if(E[i].o) break;
    		add(E[i].u,E[i].v,t-E[i].w+1);
    		add(E[i].v,E[i].u,t-E[i].w+1);
    	}
    	int ans=0;
    	while(BFS()) ans+=dfs(S,inf);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    软件工程课堂作业——计算最优惠价格
    团队项目——NABC
    二位数组
    第二次冲刺阶段 站立会议06
    第二阶段冲刺 站立会议05
    第二阶段冲刺 站立会议04
    第二阶段冲刺 站立会议03
    课程建议
    站立会议02
    第二阶段冲刺 站立会议01
  • 原文地址:https://www.cnblogs.com/asuldb/p/10548832.html
Copyright © 2011-2022 走看看