用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; }