感觉CQOI的难度挺好的,比较贴近自身,所以拿出来做了一下
CQOI2016 Day1 T1:不同的最小割
涉及算法:最小割/分治/最小割树
思路:
最小割树裸题,直接分治最小割,记录下答案,最后排序一下,统计不同的答案即可
CODE:
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } #define maxn 1000 #define maxm 100010 int n,m,q,t,ans[maxn],tot,id[maxn],tmp[maxn]; struct Edgenode{int next,to,cap;}edge[maxm]; int head[maxn],cnt=1; void add(int u,int v,int w) {cnt++; edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].cap=w;} void insert(int u,int v,int w) {add(u,v,w); add(v,u,w);} int dis[maxn],que[maxn<<1],cur[maxn],S,T; bool bfs() { memset(dis,-1,sizeof(dis)); que[0]=S; dis[S]=0; int he=0,ta=1; while (he<ta) { int now=que[he++]; for (int i=head[now]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==-1) dis[edge[i].to]=dis[now]+1,que[ta++]=edge[i].to; } return dis[T]!=-1; } int dfs(int loc,int low) { if (loc==T) return low; int w,used=0; for (int i=cur[loc]; i; i=edge[i].next) if (edge[i].cap && dis[edge[i].to]==dis[loc]+1) { w=dfs(edge[i].to,min(low-used,edge[i].cap)); edge[i].cap-=w; edge[i^1].cap+=w; used+=w; if (edge[i].cap) cur[loc]=i; if (used==low) return low; } if (!used) dis[loc]=-1; return used; } #define inf 0x7fffffff int dinic() { int tmp=0; while (bfs()) { for (int i=1; i<=n; i++) cur[i]=head[i]; tmp+=dfs(S,inf); } return tmp; } void init() { cnt=1; memset(ans,0,sizeof(ans)); memset(head,0,sizeof(head)); } bool visit[maxn]; void DFS(int x) { visit[x]=1; for (int i=head[x]; i; i=edge[i].next) if (edge[i].cap && !visit[edge[i].to]) DFS(edge[i].to); } void work(int L,int R) { if (L==R) return; for (int i=2; i<=cnt; i+=2) edge[i].cap=edge[i^1].cap=(edge[i].cap+edge[i^1].cap)>>1; S=id[L],T=id[R]; int maxflow=dinic(); memset(visit,0,sizeof(visit)); DFS(S); // for (int i=1; i<=n; i++) if (visit[i]) // for (int j=1; j<=n; j++) if (!visit[j]) // ans[i][j]=ans[j][i]=min(ans[i][j],maxflow); ans[++tot]=maxflow; int l=L,r=R; for (int i=L; i<=R; i++) if (visit[id[i]]) tmp[l++]=id[i]; else tmp[r--]=id[i]; for (int i=L; i<=R; i++) id[i]=tmp[i]; work(L,l-1); work(r+1,R); } int main() { // freopen("mincuto.in","r",stdin); // freopen("mincuto.out","w",stdout); init(); n=read(),m=read(); for (int i=1; i<=n; i++) id[i]=i; for (int u,v,w,i=1; i<=m; i++) u=read(),v=read(),w=read(),insert(u,v,w); work(1,n); sort(ans+1,ans+tot+1); int an=1; for (int i=2; i<=tot; i++) if (ans[i]!=ans[i-1]) an++; printf("%d\n",an); return 0; }