zoukankan      html  css  js  c++  java
  • [bzoj2561]最小生成树_网络流_最小割_最小生成树

    最小生成树 bzoj-2561

    题目大意;题目链接

    注释:略。


    想法:

    我们发现:

    如果一条权值为$L$的边想加入到最小生成树上的话,需要满足一下条件。

    就是求出原图的最小生成树之后,这个边当做非树边的情况下覆盖的边的最小值不可以比$L$小。

    如此,我们级就可以通过网络流来求了。

    对于每一条比$L$小的边,我们连双向边,求当前边$u,v$的最小割即可。

    如果是最大生成树的话同理,我们只需要把所有比当前加入的边的权值小的边在网络流中连无向边,然后跑最小割即可。

    Code:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #define N 200100 
    #define M 2000100 
    using namespace std;
    int to[M<<1],head[N],nxt[M<<1],val[M<<1],dis[N],tot=1,S,T;
    queue<int>q;
    struct Node {int x,y,w;}e[M]; inline bool cmp_w(const Node &a,const Node &b) {return a.w<b.w;}
    char *p1,*p2,buf[100000];
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int rd() {int x=0,f=1; char c=nc(); while(c<48) {if(c=='-') f=-1; c=nc();} while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x*f;}
    inline void add(int x,int y,int z)
    {
    	to[++tot]=y; val[tot]=z; nxt[tot]=head[x]; head[x]=tot;
    	to[++tot]=x; val[tot]=0; nxt[tot]=head[y]; head[y]=tot;
    }
    bool bfs()
    {
    	memset(dis,-1,sizeof dis); while(!q.empty()) q.pop();
    	dis[S]=0; q.push(S); while(!q.empty())
    	{
    		int x=q.front(); q.pop(); for(int i=head[x];i;i=nxt[i]) if(dis[to[i]]==-1&&val[i]>0)
    		{
    			dis[to[i]]=dis[x]+1; q.push(to[i]);
    			if(to[i]==T) return true;
    		}
    	}
    	return false;
    }
    int dinic(int x,int fl)
    {
    	int tmp=fl; if(x==T) return fl; for(int i=head[x];i;i=nxt[i]) if(dis[to[i]]==dis[x]+1&&val[i]>0)
    	{
    		int mdl=dinic(to[i],min(val[i],tmp));
    		if(!mdl) dis[to[i]]=-1;
    		val[i]-=mdl; tmp-=mdl; val[i^1]+=mdl;
    		if(!tmp) break;
    	}
    	return fl-tmp;
    }
    int main()
    {
    	int n=rd(),m=rd(); for(int i=1;i<=m;i++) e[i].x=rd(),e[i].y=rd(),e[i].w=rd();
    	int u=rd(),v=rd(),L=rd(); S=u,T=v;
    	int ans=0;
    	for(int i=1;i<=m;i++) if(e[i].w<L) add(e[i].x,e[i].y,1),add(e[i].y,e[i].x,1);
    	while(bfs()) ans+=dinic(u,1<30);
    	memset(head,0,sizeof head); tot=1;
    	for(int i=1;i<=m;i++) if(e[i].w>L) add(e[i].x,e[i].y,1),add(e[i].y,e[i].x,1);
    	while(bfs()) ans+=dinic(u,1<<30);
    	cout << ans << endl ;
    	return 0;
    }
    

     小结:好玩吧。

  • 相关阅读:
    touch测试
    JS动画代码
    前端css、javascript在线工具
    横向广告(商品)滚动
    写点js的小函数(一)
    HTML5 css reset
    JS新API标准 地理定位(navigator.geolocation)
    写点js的小函数(二、文本框的提示)
    传说中的comet(ajax版)?
    lhgdialog 4.2.0 正式版发布
  • 原文地址:https://www.cnblogs.com/ShuraK/p/10244778.html
Copyright © 2011-2022 走看看