• bzoj2561: 最小生成树


    如果出现在最小生成树上,那么此时比该边权值小的边无法连通uv。据此跑最小割(最大流)即可。

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define rep(i,n) for(int i=1;i<=n;i++)
    #define clr(x,c) memset(x,c,sizeof(x))
    int read(){
    	int x=0;char c=getchar();bool f=true;
    	while(!isdigit(c)) {
    		if(c=='-') f=false;c=getchar();
    	}
    	while(isdigit(c)) x=x*10+c-'0',c=getchar();
    	return f?x:-x;
    }
    const int nmax=20005;
    const int maxn=200005;
    const int inf=0x7f7f7f7f;
    struct Edge{
    	int from,to,cap;
    	bool operator<(const Edge&rhs)const{
    	  return cap<rhs.cap;}
    };
    Edge Edges[maxn];
    struct edge{
    	int to,cap;edge *next,*rev;
    };
    edge edges[maxn<<2],*pt,*head[nmax],*p[nmax],*cur[nmax];
    void add(int u,int v,int d){
    	pt->to=v;pt->cap=d;pt->next=head[u];head[u]=pt++;
    }
    void adde(int u,int v,int d){
    	add(u,v,d);add(v,u,0);head[u]->rev=head[v];head[v]->rev=head[u];
    }
    int cnt[nmax],h[nmax];
    int maxflow(int s,int t,int n){
    	clr(cnt,0);clr(h,0);cnt[0]=n;
    	int flow=0,a=inf,x=s;edge *e;
    	while(h[s]<n){
    		for(e=cur[x];e;e=e->next) if(e->cap>0&&h[e->to]+1==h[x]) break;
    		if(e){
    			p[e->to]=cur[x]=e;a=min(a,e->cap);x=e->to;
    			if(x==t){
    				while(x!=s) p[x]->rev->cap+=a,p[x]->cap-=a,x=p[x]->rev->to;
    				flow+=a,a=inf;
    			}
    		}else{
    			if(!--cnt[h[x]]) break;
    			h[x]=n;
    			for(e=head[x];e;e=e->next) if(e->cap>0&&h[e->to]+1<h[x]) h[x]=h[e->to]+1,cur[x]=e;
    			cnt[h[x]]++;
    			if(x!=s) x=p[x]->rev->to;
    		}
    	}
    	return flow;
    }
    int main(){
    	int n=read(),m=read(),s,t,d;
    	rep(i,m) Edges[i].from=read(),Edges[i].to=read(),Edges[i].cap=read();
    	s=read(),t=read(),d=read();
    	sort(Edges+1,Edges+m+1);
    //	rep(i,m) printf("%d %d %d
    ",Edges[i].from,Edges[i].to,Edges[i].cap);
    	pt=edges;clr(head,0);
    	rep(i,m){
    		if(Edges[i].cap>=d) break;
    		Edge&o=Edges[i];adde(o.from,o.to,1);adde(o.to,o.from,1);
    	}
    	int ans=maxflow(s,t,n);
    	pt=edges;clr(head,0);
    	for(int i=m;i;i--){
    		if(Edges[i].cap<=d) break;
    		Edge&o=Edges[i];adde(o.from,o.to,1);adde(o.to,o.from,1);
    	}
    	ans+=maxflow(s,t,n);
    	printf("%d
    ",ans);
    	return 0;
    }
    

     

    2561: 最小生成树

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1459  Solved: 716
    [Submit][Status][Discuss]

    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

     输出一行一个整数表示最少需要删掉的边的数量。

    Sample Input

    3 2
    3 2 1
    1 2 3
    1 2 2

    Sample Output

    1

    HINT

    对于20%的数据满足N ≤ 10,M ≤ 20,L ≤ 20;

      对于50%的数据满足N ≤ 300,M ≤ 3000,L ≤ 200;

      对于100%的数据满足N ≤ 20000,M ≤ 200000,L ≤ 20000。

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    div中子div在firefox ie 水平居中对齐
    Access数据库自定义连接字符串(详细有图百度文档)
    ASP页面乱码
    国内开源asp.netCMS汇总
    sql 2005
    卡巴斯基授权key导入方式方法及其导入key基本原理
    关于SqlServer服务无法启动的症状分析和解决方法
    js下流媒体的在线播放
    用JS+vml作三维报表
    了解嵌入式数据库(sqlite,firebird)
  • 原文地址:https://www.cnblogs.com/fighting-to-the-end/p/5657280.html
Copyright © 2020-2023  润新知