• bzoj4519: [Cqoi2016]不同的最小割(最小割树)


    传送门

    好神仙……最小割树是个什么东西……

    其实我觉得干脆直接$O(n^2)$跑几个dinic算了……

    来说一下这个叫最小割树的神奇东西

    我们先建一个$n$个点,没有边的无向图

    在原图中任选两点$s,t$,然后跑一遍最小割。那么在残量网络上的点会分成两个集合,一个属于$s$,一个属于$t$

    我们在无向图中连接$s,t$两点,边权为最小割

    然后分别对$s$的点集和$t$的点集递归做以上过程,直到生成一棵树

    那么原图中任意两点的最小割就是他们树上路径的最小值

    证明?(能用就好要什么证明)

    感性理解一下吧……

    因为题目只要求不同的最小割的个数

    那么只要用一个set存一下就好了

     1 //minamoto
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<set>
     7 #include<queue>
     8 #define inf 0x3f3f3f3f
     9 using namespace std;
    10 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    11 char buf[1<<21],*p1=buf,*p2=buf;
    12 inline int read(){
    13     #define num ch-'0'
    14     char ch;bool flag=0;int res;
    15     while(!isdigit(ch=getc()))
    16     (ch=='-')&&(flag=true);
    17     for(res=num;isdigit(ch=getc());res=res*10+num);
    18     (flag)&&(res=-res);
    19     #undef num
    20     return res;
    21 }
    22 const int N=1005,M=20005;
    23 int head[N],Next[M],ver[M],edge[M],ee[M],tot=1;
    24 int dep[N],cur[N],vis[N],n,m,s,t;
    25 queue<int> q;set<int> S;
    26 inline void add(int u,int v,int e){
    27     ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=ee[tot]=e;
    28     ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=ee[tot]=e;
    29 }
    30 inline void clear(){
    31     for(int i=2;i<=tot;++i) edge[i]=ee[i];
    32 }
    33 bool bfs(){
    34     while(!q.empty()) q.pop();
    35     for(int i=1;i<=n;++i) cur[i]=head[i];
    36     memset(dep,-1,sizeof(dep));
    37     q.push(s),dep[s]=0;
    38     while(!q.empty()){
    39         int u=q.front();q.pop();
    40         for(int i=head[u];i;i=Next[i]){
    41             int v=ver[i];
    42             if(dep[v]<0&&edge[i]){
    43                 dep[v]=dep[u]+1,q.push(v);
    44                 if(v==t) return true;
    45             }
    46         }
    47     }
    48     return false;
    49 }
    50 int dfs(int u,int limit){
    51     if(u==t||!limit) return limit;
    52     int flow=0,f;
    53     for(int i=cur[u];i;cur[u]=i=Next[i]){
    54         int v=ver[i];
    55         if(dep[v]==dep[u]+1&&(f=dfs(v,min(limit,edge[i])))){
    56             flow+=f,limit-=f;
    57             edge[i]-=f,edge[i^1]+=f;
    58             if(!limit) break;
    59         }
    60     }
    61     return flow;
    62 }
    63 int dinic(){
    64     int flow=0;
    65     while(bfs()) flow+=dfs(s,inf);
    66     return flow;
    67 }
    68 void find(int u){
    69     vis[u]=1;
    70     for(int i=head[u];i;i=Next[i]){
    71         int v=ver[i];
    72         if(!vis[v]&&edge[i]) find(v);
    73     }
    74 }
    75 void check(){
    76     clear();
    77     S.insert(dinic());
    78     memset(vis,0,sizeof(vis));
    79     find(s);
    80 }
    81 int p[N];
    82 int main(){
    83     //freopen("testdata.in","r",stdin);
    84     n=read(),m=read();
    85     for(int i=1;i<=m;++i){
    86         int u=read(),v=read(),e=read();add(u,v,e);
    87     }
    88     for(int i=2;i<=n;++i) p[i]=1;
    89     for(int i=2;i<=n;++i){
    90         s=i,t=p[i];
    91         check();
    92         for(int j=i;j<=n;++j)
    93         if(p[j]==t&&vis[j]) p[j]=s;
    94     }
    95     printf("%d
    ",S.size());
    96     return 0;
    97 }
  • 相关阅读:
    Re:从零开始的领域驱动设计
    领域驱动设计和Spring
    深入JVM分析spring-boot应用hibernate-validator
    深入Spring Boot:那些注入不了的Spring占位符(${}表达式)
    Android 使用OKhttp获取response时遇到的坑
    Android EditText组件drawableLeft属性设置的图片和hint设置的文字之间的距离
    Android 自定义spinner下拉框实现的实现
    Android You need to use a Theme.AppCompat theme (or descendant) with this activity.
    Android中取消GridView & ListView默认的点击背景色
    Android 显示 PDF 文件
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9570614.html
Copyright © 2020-2023  润新知