bzoj 4519 [Cqoi2016]不同的最小割

来源:互联网 发布:step文件打开软件 编辑:程序博客网 时间:2024/05/21 10:27

用Gusfield算法建出Gomory-Hu树,之后统计有多少不同的最小割就可以了~

不了解Gusfield算法与Gomory-Hu树的话可以查查相关资料~

代码:


#include<iostream>#include<cstdio>#include<algorithm>#include<cstdlib>using namespace std;typedef long long LL;const LL INF=0x7ffffffffffffLL;//long long!!! struct front_star{LL ne,to,v;}a[100005];LL h[100005],cnt=1,q[1000005],f[1005][1005],N,M,tot,dis[100005],Gap[100005];LL vst[100005],prt[100005];void Addedge(LL x,LL y,LL v){   a[++cnt].to=y;a[cnt].ne=h[x];a[cnt].v=v;h[x]=cnt;    a[++cnt].to=x;a[cnt].ne=h[y];a[cnt].v=0;h[y]=cnt;}LL DFS(LL S,LL x,LL maxf,LL T){   if(x==T)return maxf;    LL y,k,ret=0,dlt;    for(k=h[x];k;k=a[k].ne)      {y=a[k].to;       if(a[k].v&&dis[x]==dis[y]+1)         {dlt=DFS(S,y,min(maxf,a[k].v),T);          a[k].v-=dlt;a[k^1].v+=dlt;          maxf-=dlt;ret+=dlt;          if(!maxf||dis[S]>=tot)return ret;         }      }    if(!(--Gap[dis[x]]))dis[S]=tot;    Gap[++dis[x]]++;    return ret;}LL Sap(LL S,LL T){   LL i,ret=0;    for(i=0;i<=N;i++)dis[i]=Gap[i]=0;    Gap[0]=tot=N;    while(dis[S]<tot)ret+=DFS(S,S,INF,T);    return ret;}void DFS(LL x){   LL y,k;    vst[x]=1;    for(k=h[x];k;k=a[k].ne)      {y=a[k].to;       if(a[k].v&&!vst[y])DFS(y);      }}void Gusfield(){   LL i,j,ans;    for(i=0;i<=N;i++)for(j=0;j<=N;j++)f[i][j]=INF;    for(i=2;i<=N;i++)prt[i]=1;    for(i=2;i<=N;i++)      {for(j=2;j<=cnt;j+=2){a[j].v+=a[j+1].v;a[j+1].v=0;}       for(j=1;j<=N;j++)vst[j]=0;       ans=Sap(prt[i],i);       DFS(prt[i]);       for(j=i+1;j<=N;j++)if(!vst[j]&&prt[i]==prt[j])prt[j]=i;       for(j=1;j<i;j++)f[i][j]=f[j][i]=min(f[prt[i]][j],ans);      }}int main(){   LL i,j,x,y,v,ans;    scanf("%lld%lld",&N,&M);    for(i=1;i<=M;i++)      {scanf("%lld%lld%lld",&x,&y,&v);       Addedge(x,y,v);Addedge(y,x,v);      }    Gusfield();    for(i=1;i<=N;i++)       for(j=i+1;j<=N;j++)q[++q[0]]=f[i][j];    sort(q+1,q+1+q[0]);    ans=unique(q+1,q+1+q[0])-q-1;    printf("%lld",ans);    return 0;}


1 0
原创粉丝点击