BZOJ3345: Pku2914 Minimum Cut

真的是日了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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值