BZOJ3345: Pku2914 Minimum Cut
发布日期:2021-05-06 03:50:30 浏览次数:36 分类:原创文章

本文共 1751 字,大约阅读时间需要 5 分钟。

真的是日了DOG了 发现Mincut返回错东西了

关于最小割的话我们可以任取一个点作为S 然后枚举T进行最大流
时间复杂度显然是
O(n4) 那么我们跑不过去
这了我们需要的是一个叫Stoer wagner的算法 时间复杂度为 O(n3)

算法的整体思想是不停的将图缩点并在缩点过程中更新答案

每次扩展一个当前联通度最大的节点并更新其他未扩展节点的联通度直到无节点可以继续扩展
这时候我们有一个扩展节点的顺序 将最后扩展的节点的联通度用来更新答案 取最后扩展的两个点缩点 (这里与倒数第二个节点缩点是为了让可更新更小)
每一次我们都回找到一个点 这个点代表了一个点集 而这个点的联通度就是这个点集 于这个点集的补集的割

具体实现看代码

#include<cstdio>#include<cstring>#include<iostream>#include<cstdlib>#include<queue>using namespace std;char c;inline void read(int &a){    a=0;do c=getchar();while(c<'0'||c>'9');    while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}int M[501][501];int n;struct Res{    int len,u,v;    inline friend bool operator<(Res a,Res b){  return a.len<b.len;}};int size[501],f[501];int find(int x){  return f[x]==x?x:f[x]=find(f[x]);}void Union(int u,int v){  if(size[u]<size[v])swap(u,v);f[u]=f[v];if(size[u]==size[v])size[u]++;}int Du[501];bool use[501];int Mincut(){    int res=1<<29,tp;    for(int i=1;i<n;i++)    {        for(int j=1;j<=n;j++)use[j]=false,f[j]=j,size[j]=1,Du[j]=0;        Res R;tp=0;        int u=1,v=1;        for(int j=1;j<=n;j++)            Du[j]+=M[u][j];        use[1]=true;       for(int j=1;j+i<=n;j++)       {            u=v;            v=0;            for(int k=1;k<=n;k++)                if(use[k]==false&&Du[k]>Du[v])v=k;            use[v]=true;            for(int k=1;k<=n;k++)             Du[k]+=M[v][k];       }      res=min(res,Du[v]);      if(u>v)swap(u,v);      for(int i=1;i<=n;i++)        if(M[i][v])            M[u][i]=M[i][u]+=M[i][v],M[v][i]=M[i][v]=0;      M[u][v]=0,M[u][u]=0;    }   return res;}int main(){    int m;    read(n),read(m);    for(int i=1;i<=m;i++)        {            int j,k;read(j),read(k),read(M[j][k]),M[k][j]=M[j][k];        }    int ans=Mincut();    printf("%d\n",ans);}
上一篇:BZOJ1338: Pku1981 Circle and Points单位圆覆盖
下一篇:BZOJ2391: Cirno的忧郁

发表评论

最新留言

很好
[***.229.124.182]2025年03月26日 12时02分00秒