zoukankan      html  css  js  c++  java
  • bzoj 2561: 最小生成树

    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。

    题解:

    我们在做MST时,都会按边从大到小排序 判断两点间是否连通,然后加入,此题同理

    若我们要在u,v之间加入长度为L的边且满足最小生成树,那么我们就要保证u,v之间不存在连通路径,且路径上最小边<L

    所以我们就把<L的边加边,容量为1,跑一遍最小割即可,最大生成树情况同理,答案累加即可

     1  #include <algorithm>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #define RG register
     8 using namespace std;
     9 const int N=20005,M=200005,INF=2e9;
    10 int head[N],num=1;
    11 struct Lin{
    12     int next,to,dis;
    13 }a[M<<1];
    14 void init(int x,int y,int z){
    15     a[++num].next=head[x];
    16     a[num].to=y;a[num].dis=z;
    17     head[x]=num;
    18 }
    19 void addedge(int x,int y,int z){
    20     init(x,y,z);init(y,x,z);
    21 }
    22 int S,T;
    23 struct node{
    24     int x,y,dis;
    25     bool operator <(const node &pp)const{
    26         return dis<pp.dis;
    27     }
    28 }e[M];
    29 int n,m,dep[N],q[N];
    30 void Clear(){
    31     num=1;
    32     memset(head,0,sizeof(head));
    33 }
    34 bool bfs(){
    35     memset(dep,0,sizeof(dep));
    36     RG int x,u,t=0,sum=1;
    37     q[1]=S;dep[S]=1;
    38     while(t!=sum){
    39         x=q[++t];
    40         for(RG int i=head[x];i;i=a[i].next){
    41             u=a[i].to;
    42             if(dep[u] || a[i].dis<=0)continue;
    43             dep[u]=dep[x]+1;q[++sum]=u;
    44         }
    45     }
    46     return dep[T];
    47 }
    48 int dfs(int x,int flow){
    49     if(x==T || !flow)return flow;
    50     int tot=0;int tmp,u;
    51     for(RG int i=head[x];i;i=a[i].next){
    52         u=a[i].to;
    53         if(dep[u]!=dep[x]+1 || a[i].dis<=0)continue;
    54         tmp=dfs(u,min(flow,a[i].dis));
    55         tot+=tmp;flow-=tmp;
    56         a[i].dis-=tmp;a[i^1].dis+=tmp;
    57         if(!flow)break;
    58     }
    59     if(!tot)dep[x]=0;
    60     return tot;
    61 }
    62 int maxflow(){
    63     int tot=0,tmp;
    64     while(bfs()){
    65         tmp=dfs(S,INF);
    66         while(tmp)tot+=tmp,tmp=dfs(S,INF);
    67     }
    68     return tot;
    69 }
    70 void work(){
    71     scanf("%d%d",&n,&m);
    72     for(int i=1;i<=m;i++)
    73         scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].dis);
    74     sort(e+1,e+m+1);
    75     int vs,ans=0;
    76     scanf("%d%d%d",&S,&T,&vs);
    77     for(int i=1;i<=m;i++){
    78         if(e[i].dis>=vs)break;
    79         addedge(e[i].x,e[i].y,1);
    80     }
    81     ans+=maxflow();Clear();
    82     for(int i=m;i>=1;i--){
    83         if(e[i].dis<=vs)break;
    84         addedge(e[i].x,e[i].y,1);
    85     }
    86     ans+=maxflow();
    87     printf("%d
    ",ans);
    88 }
    89 int main()
    90 {
    91     work();
    92     return 0;
    93 }
     
  • 相关阅读:
    word设置的密码忘了怎么办?
    Navicat Report Viewer 设置 HTTP 的方法
    如何处理Navicat Report Viewer 报表
    excel密码忘记了怎么办
    Beyond Compare文本比较搜索功能详解
    Popular Cows POJ
    Problem B. Harvest of Apples HDU
    网络流模型整理
    The Shortest Statement CodeForces
    Vasya and Multisets CodeForces
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7215095.html
Copyright © 2011-2022 走看看