4519: [Cqoi2016]不同的最小割

    xiaoxiao2023-03-25  6

    4519: [Cqoi2016]不同的最小割

    Time Limit: 20 Sec   Memory Limit: 512 MB Submit: 524   Solved: 325 [ Submit][ Status][ Discuss]

    Description

    学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成 两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割。对于带权图来说,将 所有顶点处在不同部分的边的权值相加所得到的值定义为这个割的容量,而s,t的最小割指的是在 关于s,t的割中容量最小的割。 而对冲刺NOI竞赛的选手而言,求带权图中两点的最小割已经不是什么难事了。我们可以把 视野放宽,考虑有N个点的无向连通图中所有点对的最小割的容量,共能得到N(N−1) 2个数值。 这些数值中互不相同的有多少个呢?这似乎是个有趣的问题。

    Input

    输入文件第一行包含两个数N,M,表示点数和边数。接下来M行,每行三个数u,v,w, 表示点u和点v(从1开始标号)之间有条边权值是w。 1<=N<=850 1<=M<=8500 1<=W<=100000

    Output

     输出文件第一行为一个整数,表示个数。

    Sample Input

    4 4 1 2 3 1 3 6 2 4 5 3 4 4

    Sample Output

    3

    HINT

    Source

    [ Submit][ Status][ Discuss] 构建一棵最小割树即可 传送门 Dinic打残了。。 #include<iostream> #include<cstdio> #include<queue> #include<vector> #include<bitset> #include<algorithm> #include<cstring> #include<map> #include<stack> #include<set> #include<cmath> #include<ext/pb_ds/priority_queue.hpp> using namespace std; const int maxn = 1E3 + 10; const int maxm = 1E5 + 10; const int INF = ~0U>>1; struct E{ int to,cap,flow; E(){} E(int to,int cap,int flow): to(to),cap(cap),flow(flow){} }edgs[maxm]; int n,m,s,t,cur[maxn],L[maxn],fa[maxn],va[maxn] ,cnt,Cnt,x[maxm],y[maxm],w[maxm],vis[maxn]; vector <int> v[maxn]; queue <int> Q; void Add(int x,int y,int cap) { v[x].push_back(cnt); edgs[cnt++] = E(y,cap,0); v[y].push_back(cnt); edgs[cnt++] = E(x,0,0); } bool BFS() { L[s] = 1; vis[s] = ++Cnt; Q.push(s); while (!Q.empty()) { int k = Q.front(); Q.pop(); for (int i = 0; i < v[k].size(); i++) { E e = edgs[v[k][i]]; if (e.cap == e.flow) continue; if (vis[e.to] == Cnt) continue; vis[e.to] = Cnt; L[e.to] = L[k] + 1; Q.push(e.to); } } return vis[t] == Cnt; } int Dicnic(int x,int a) { if (x == t) return a; int flow = 0; for (int &i = cur[x]; i < v[x].size(); i++) { E &e = edgs[v[x][i]]; if (e.cap == e.flow) continue; if (L[e.to] != L[x] + 1) continue; int f = Dicnic(e.to,min(a,e.cap - e.flow)); if (!f) continue; e.flow += f; edgs[v[x][i]^1].flow -= f; a -= f; flow += f; if (!a) return flow; } if (!flow) L[x] = -1; return flow; } int getint() { char ch = getchar(); int ret = 0; while (ch < '0' || '9' < ch) ch = getchar(); while ('0' <= ch && ch <= '9') ret = ret*10 + ch - '0',ch = getchar(); return ret; } int main() { #ifdef DMC freopen("DMC.txt","r",stdin); #endif n = getint(); m = getint(); for (int i = 1; i <= m; i++) { int x = getint(); int y = getint(); int w = getint(); Add(x,y,w); Add(y,x,w); } for (int i = 2; i <= n; i++) fa[i] = 1; for (int i = 2; i <= n; i++) { s = i; t = fa[i]; int MaxFlow = 0; while (BFS()) { for (int i = 1; i <= n; i++) cur[i] = 0; MaxFlow += Dicnic(s,INF); } va[i] = MaxFlow; for (int j = i + 1; j <= n; j++) if (fa[j] == fa[i] && vis[j] == Cnt) fa[j] = i; for (int i = 0; i < cnt; i++) edgs[i].flow = 0; } sort(va + 2,va + n + 1); int Ans = 0; va[1] = -INF; for (int i = 2; i <= n; i++) if (va[i] != va[i-1]) ++Ans; cout << Ans; return 0; }

    转载请注明原文地址: https://ju.6miu.com/read-1203950.html
    最新回复(0)