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),那么需要删掉最少多少条边,才能够使得这条边既可能出现在最小生成树上,也可能出现在最大生成树上?

    Solution

    题意:在一个图中,问一条边即在最小生成树上,又在最大生成树上需要从图上删掉多少条边

    在最小生成树上,一条边不被选择的充要条件是什么呢?

    当比它小的边已经将它所连接的两点连接起来的时候,这条边就不能被选了

    最大生成树同样

    那么,先只考虑最小生成树的情况

    如果这条边不在最小生成树中,边权比它小的边一定联通了这条边所接的节点u和v

    我们想要花尽量少的代价使u,v不再联通

    显然问题转化为了最小割

    对最小生成树做一次再对最大生成树做一次,答案加起来就可以了

      1 #include<bits/stdc++.h>
      2 
      3 #define maxn 20000+5
      4 #define maxm 600000+5
      5 #define set(a,b) memset(a,(b),sizeof(a))
      6 #define fr(i,a,b) for(ll i=(a),_end_=(b);i<=_end_;i++)
      7 #define rf(i,b,a) for(ll i=(a),_end_=(b);i>=_end_;i--)
      8 #define fe(i,a,b) for(int i=first[(b)],_end_=(a);i!=_end_;i=s[i].next)
      9 #define fec(i,a,b) for(int &i=cur[(b)],_end_=(a);i!=_end_;i=s[i].next)
     10 
     11 using namespace std;
     12 
     13 typedef long long ll;
     14 
     15 struct sides{
     16   int u,v,c;
     17   int next;
     18 }s[maxm];
     19 
     20 struct edge{
     21   int u,v,w;
     22   friend bool operator < (edge a,edge b){
     23     return a.w<b.w;
     24   }
     25 }e[maxm];
     26 
     27 queue<int> q;
     28 int h[maxn],first[maxn],cur[maxn];
     29 int ind=0;
     30 int cost=0;
     31 int n,m,sp,tp,p;
     32 
     33 bool comp(edge a,edge b)
     34 {
     35   return a.w<b.w;
     36 }
     37 
     38 void add(int u,int v,int c)
     39 {
     40   s[ind].u=u,s[ind].v=v,s[ind].c=c;
     41   s[ind].next=first[u],first[u]=ind;
     42   ind++;
     43   
     44   s[ind].u=v,s[ind].v=u,s[ind].c=c;
     45   s[ind].next=first[v],first[v]=ind;
     46   ind++;
     47 }
     48 
     49 bool bfs()
     50 {
     51   set(h,-1);
     52   h[sp]=0;
     53   q.push(sp);
     54   while( !q.empty() ){
     55     int sd=q.front();q.pop();
     56     fe(i,-1,sd)
     57       if( h[s[i].v]==-1 && s[i].c ){
     58     h[s[i].v]=h[sd]+1;
     59     q.push(s[i].v);
     60       }
     61   }
     62   return h[tp]!=-1;
     63 }
     64 
     65 int dfs(int sd,int flow)
     66 {
     67   if( sd==tp ) return flow;
     68   int w,used=0;
     69   fec(i,-1,sd)
     70     if( h[s[i].v]==h[sd]+1 && s[i].c ){
     71       w=dfs(s[i].v,min(flow-used,s[i].c));
     72       s[i].c-=w,s[i^1].c+=w;
     73       used+=w;
     74       if( used==flow ) return flow;
     75     }
     76   if( !used ) h[sd]=1;
     77   return used;
     78 }
     79 
     80 void dinic()
     81 {
     82   while( bfs() ){
     83     fr(i,0,n+1)
     84       cur[i]=first[i];
     85     cost+=dfs(sp,INT_MAX);
     86   }
     87 }
     88 
     89 void solve()
     90 {
     91   ind=0;
     92   set(first,-1);
     93   fr(i,1,m)
     94     if( e[i].w<p )
     95       add(e[i].u,e[i].v,1);
     96     else break;
     97   dinic();
     98   
     99   ind=0;
    100   set(first,-1);
    101   rf(i,1,m)
    102     if( e[i].w>p )
    103       add(e[i].u,e[i].v,1);
    104     else break;
    105   dinic();
    106 }
    107 
    108 int main()
    109 {
    110 #ifndef ONLINE_JUDGE
    111   freopen("2561.in","r",stdin);
    112   freopen("2561.out","w",stdout);
    113 #endif
    114   cin >> n >> m ;
    115   fr(i,1,m)
    116     cin >> e[i].u >> e[i].v >> e[i].w ;
    117   sort(e+1,e+m+1,comp);
    118   cin >> sp >> tp >> p ;
    119   solve();
    120   cout << cost ;
    121   return 0;
    122 }
  • 相关阅读:
    JS中的一些遍历方法
    JS中关于引用类型数据及函数的参数传递
    JS中关于数组的操作
    CSS中的一些伪类
    JS中的回调函数
    JS中关于构造函数、原型链、prototype、constructor、instanceof、__proto__属性
    JDK的安装及环境变量配置
    JS中的this指针
    JS中的数据类型
    Word中页码及目录、参考文献的制做方法
  • 原文地址:https://www.cnblogs.com/ST-Saint/p/4618368.html
Copyright © 2011-2022 走看看