您的位置:首页 > 其它

4519: [Cqoi2016]不同的最小割

2016-09-28 13:17 357 查看

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: