BZOJ 4519([Cqoi2016]不同的最小割-Gusfield算法)

来源:互联网 发布:淘宝怎么装修 编辑:程序博客网 时间:2024/05/17 08:24

题意:给一幅图,问2点之间最小割有几个不同取值。
1<=N<=850 1<=M<=8500
Gusfield算法如下:
假设一开始所有点均在同一集合
任意选定2个不在同一集合点求最小割,割把点集分成2部分,
2部分各取一点,这个值可以更新最小割。
然后将这2部分点分成不同的集合
不断循环,直到各集合均为单点。

#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<functional>#include<iostream>#include<cmath>#include<set>#include<cctype>#include<ctime>using namespace std;#define For(i,n) for(int i=1;i<=n;i++)#define Fork(i,k,n) for(int i=k;i<=n;i++)#define Rep(i,n) for(int i=0;i<n;i++)#define ForD(i,n) for(int i=n;i;i--)#define RepD(i,n) for(int i=n;i>=0;i--)#define Forp(x) for(int p=Pre[x];p;p=Next[p])#define Forpiter(x) for(int &p=iter[x];p;p=Next[p])#define Lson (x<<1)#define Rson ((x<<1)+1)#define MEM(a) memset(a,0,sizeof(a));#define SI(x) ((x).size())#define MEMI(a) memset(a,127,sizeof(a));#define MEMi(a) memset(a,128,sizeof(a));#define INF (2139062143)#define F (100000007)#define MAXN (855+100)#define MAXM (17000*2+100)long long mul(long long a,long long b){return (a*b)%F;}long long add(long long a,long long b){return (a+b)%F;}long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}typedef long long ll;int read(){    int x=0,f=1; char ch=getchar();    while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}    while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}    return x*f;} class Max_flow  //dinic+��ǰ���Ż�   {    public:        int n,t;        int q[MAXN];        int edge[MAXM],Next[MAXM],Pre[MAXN],weight[MAXM],size;        void addedge(int u,int v,int w)          {              edge[++size]=v;              weight[size]=w;              Next[size]=Pre[u];              Pre[u]=size;          }          void addedge2(int u,int v,int w){addedge(u,v,w),addedge(v,u,0);}         bool b[MAXN];        int d[MAXN];        bool SPFA(int s,int t)          {              For(i,n) d[i]=INF;            MEM(b)            d[q[1]=s]=0;b[s]=1;              int head=1,tail=1;              while (head<=tail)              {                  int now=q[head++];                  Forp(now)                  {                      int &v=edge[p];                      if (weight[p]&&!b[v])                      {                          d[v]=d[now]+1;                          b[v]=1,q[++tail]=v;                      }                  }                  }              return b[t];          }         int iter[MAXN];      int dfs(int x,int f)      {          if (x==t) return f;          Forpiter(x)          {              int v=edge[p];              if (weight[p]&&d[x]<d[v])              {                    int nowflow=dfs(v,min(weight[p],f));                    if (nowflow)                    {                      weight[p]-=nowflow;                      weight[p^1]+=nowflow;                      return nowflow;                    }              }          }          return 0;      }      int max_flow(int s,int t)      {          (*this).t=t;        int flow=0;          while(SPFA(s,t))          {              For(i,n) iter[i]=Pre[i];              int f;              while (f=dfs(s,INF))                  flow+=f;           }          return flow;      }       void mem(int n)        {            (*this).n=n;          size=1;            For(i,n) Pre[i]=0;       }    }S;  struct e{    int u,v,w;}edges[MAXM];  int n,m,f[MAXN];set<int> Set;void cut(int u,int v){    S.mem(n);    For(i,m) if (1) {        S.addedge(edges[i].u,edges[i].v,edges[i].w);        S.addedge(edges[i].v,edges[i].u,edges[i].w);    }    int ans=S.max_flow(u,v);    Set.insert(ans);}int main(){//  freopen("bzoj4519.in","r",stdin);//  freopen(".out","w",stdout);    n=read(),m=read();    For(i,m) {        int u=read(),v=read(),w=read();        edges[i].u=u,edges[i].v=v,edges[i].w=w;    }    For(i,n) f[i]=1;    Fork(i,2,n) {        int v=f[i];        cut(i,v);        Fork(j,i,n) {            if (f[j]==v&&S.b[j]) f[j]=i;        }    }    printf("%d\n",SI(Set));    return 0;}
0 0
原创粉丝点击