zoukankan      html  css  js  c++  java
  • BZOJ2561 最小生成树

    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。

     
    还是不看题解不会系列。看了题解还忽略细节系列。
    首先和最小生成树联系,一条边(u,v)能够作为MST中的一条边,条件是权值比它小的边,不能够联通u和v,所以思路来了,用权值比它小的建图,流量为1,然后求最小割即可。最大生成树同理。通过这道题让我意识到了我不熟悉我用的模板的哪个部分。
     
    但是我直接建的单向边,我发现题解都是双向边,不是太理解。然后画个这个图,就明白了。
    如果建单向边,2和3的那条边,不一定会被割掉。(易知)
     
     
    然后就发现我的模板里面addedge操作,直接就建了两条边,按照题目的数据量。20w*2*2=80w, 我开的40w不够用。
     
    还有一个地方是,我的模板,需要知道图中共有多少个点,然后只能无脑set了一波,然后又发现,建图的时候可能不会出现u,v。然后就用标记了一下,才得到总点数,比较麻烦。
     
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 const int maxn=100010;
      5 const int maxm=1000010;
      6 const int inf=0x3f3f3f3f;
      7 struct Edge{
      8     int to,next,cap,flow,cost;
      9 }edge[maxm];
     10 
     11 int tol;
     12 int head[maxn];
     13 int gap[maxn],dep[maxn],cur[maxn];
     14 void init() {
     15     tol=0;
     16     memset(head,-1,sizeof(head));
     17 }
     18 void addedge(int u,int v,int w,int rw=0) {
     19     edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
     20     edge[tol].next=head[u];head[u]=tol++;
     21     edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
     22     edge[tol].next=head[v];head[v]=tol++;
     23 }
     24 
     25 int Q[maxn];
     26 void bfs(int start,int end) {
     27     memset(dep,-1,sizeof(dep));
     28     memset(gap,0,sizeof(gap));
     29     gap[0]=1;
     30     int front=0,rear=0;
     31     dep[end]=0;
     32     Q[rear++]=end;
     33     while(front!=rear) {
     34         int u=Q[front++];
     35         for(int i=head[u];i!=-1;i=edge[i].next) {
     36             int v=edge[i].to;
     37             if(dep[v]!=-1) continue;
     38             Q[rear++]=v;
     39             dep[v]=dep[u]+1;
     40             gap[dep[v]]++;
     41         }
     42     }
     43 }
     44 
     45 int S[maxn];
     46 int sap(int start,int end,int n) {
     47     bfs(start,end);
     48     memcpy(cur,head,sizeof(head));
     49     int top=0;
     50     int u=start;
     51     int ans=0;
     52     while(dep[start]<n) {
     53         if(u==end) {
     54             int minn=inf;
     55             int inser;
     56             for(int i=0;i<top;i++) {
     57                 if(minn>edge[S[i]].cap-edge[S[i]].flow) {
     58                     minn=edge[S[i]].cap-edge[S[i]].flow;
     59                     inser=i;
     60                 }
     61             }
     62             for(int i=0;i<top;i++) {
     63                 edge[S[i]].flow+=minn;
     64                 edge[S[i]^1].flow-=minn;
     65             }
     66             ans+=minn;
     67             top=inser;
     68             u=edge[S[top]^1].to;
     69             continue;
     70         }
     71         bool flag=false;
     72         int v;
     73         for(int i=cur[u];i!=-1;i=edge[i].next) {
     74             v=edge[i].to;
     75             if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u]) {
     76                 flag=true;
     77                 cur[u]=i;
     78                 break;
     79             }
     80         }
     81         if(flag) {
     82             S[top++]=cur[u];
     83             u=v;
     84             continue;
     85         }
     86         int minn=n;
     87         for(int i=head[u];i!=-1;i=edge[i].next) {
     88             if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<minn) {
     89                 minn=dep[edge[i].to];
     90                 cur[u]=i;
     91             }
     92         }
     93         gap[dep[u]]--;
     94         if(!gap[dep[u]]) return ans;
     95         dep[u]=minn+1;
     96         gap[dep[u]]++;
     97         if(u!=start) u=edge[S[--top]^1].to;
     98     }
     99     return ans;
    100 }
    101 
    102 struct node{
    103     int u,v,w;
    104     bool operator <(const node &b)const {
    105         return w<b.w;
    106     }
    107 }edge_2[maxm];
    108 
    109 int main() {
    110     int n,m;
    111     while(~scanf("%d%d",&n,&m)) {
    112         for(int i=1;i<=m;i++) {
    113             scanf("%d%d%d",&edge_2[i].u,&edge_2[i].v,&edge_2[i].w);
    114         }
    115         sort(edge_2+1,edge_2+m+1);
    116         int u,v,l,ans=0,tmp;
    117         scanf("%d%d%d",&u,&v,&l);
    118         init();
    119         set<int> sit;
    120         bool flagu=false,flagv=false;
    121         for(int i=1;i<=m;i++) {
    122             if(edge_2[i].w<l) {
    123                 if(edge_2[i].u==u||edge_2[i].v==u) flagu=true;
    124                 if(edge_2[i].u==v||edge_2[i].v==v) flagv=true;
    125                 addedge(edge_2[i].u,edge_2[i].v,1);
    126                 addedge(edge_2[i].v,edge_2[i].u,1);
    127                 sit.insert(edge_2[i].u);
    128                 sit.insert(edge_2[i].v);
    129             } else break;
    130         }
    131         tmp=2-flagu-flagv;
    132         ans+=sap(u,v,sit.size()+tmp);
    133         init();
    134         sit.clear();
    135         flagu=false,flagv=false;
    136         for(int i=m;i>=1;i--) {
    137             if(edge_2[i].w>l) {
    138                 if(edge_2[i].u==u||edge_2[i].v==u) flagu=true;
    139                 if(edge_2[i].u==v||edge_2[i].v==v) flagv=true;
    140                 addedge(edge_2[i].u,edge_2[i].v,1);
    141                 addedge(edge_2[i].v,edge_2[i].u,1);
    142                 sit.insert(edge_2[i].u);
    143                 sit.insert(edge_2[i].v);
    144             } else break;
    145         }
    146         tmp=2-flagu-flagv;
    147         ans+=sap(u,v,sit.size());
    148         printf("%d
    ",ans);
    149     }
    150 }
     
     
  • 相关阅读:
    Prometheus监控k8s集合
    docker集合
    开源堡垒机jumpserver
    ELK日志分析平台
    安全名称解释
    CPU上下文切换
    平均负载
    234. 回文链表
    125. 验证回文串
    122. 买卖股票的最佳时机II
  • 原文地址:https://www.cnblogs.com/ACMerszl/p/10806211.html
Copyright © 2011-2022 走看看