P4123 [CQOI2016]不同的最小割

题意

前置知识:最小割树,不会去模板学学。

会了模板这题就很裸了,直接就最小割树,求有多少种不同的边权即可。

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=910;
const int maxm=9010;
const int inf=1e9;
int n,m,cnt_edge=1,S,T,tim,ans;
int a[maxn],tmp[maxn],head[maxn],dep[maxn],cur[maxn],col[maxn];
unordered_map<int,bool>mp;
struct edge{int to,nxt,w,flow;}e[maxm<<1];
inline void add(int u,int v,int w)
{
    e[++cnt_edge].nxt=head[u];
    head[u]=cnt_edge;
    e[cnt_edge].to=v;
    e[cnt_edge].w=w;
    e[cnt_edge].flow=0;
}
inline bool bfs()
{
    memset(dep,0,sizeof(dep));
    memset(cur,0,sizeof(cur));
    queue<int>q;
    q.push(S);dep[S]=1;cur[S]=head[S];
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(dep[y]||e[i].flow>=e[i].w)continue;
            dep[y]=dep[x]+1;cur[y]=head[y];
            q.push(y);
        }
    }
    return dep[T]>0;
}
int dfs(int x,int lim)
{
    if(x==T||lim<=0)return lim;
    int res=lim;
    for(int i=cur[x];i;i=e[i].nxt)
    {
        cur[x]=i;
        int y=e[i].to;
        if(dep[y]!=dep[x]+1||e[i].flow>=e[i].w)continue;
        int tmp=dfs(y,min(res,e[i].w-e[i].flow));
        if(tmp<=0)dep[y]=0;
        res-=tmp;
        e[i].flow+=tmp;e[i^1].flow-=tmp;
        if(res<=0)break;
    }
    return lim-res;
}
inline int Dinic(int x,int y)
{
    S=x,T=y;
    int res=0;
    for(int i=2;i<=cnt_edge;i++)e[i].flow=0;
    while(bfs())res+=dfs(S,inf);
    return res;
}
void getcol(int x,int c)
{
    col[x]=c;
    for(int i=head[x];i;i=e[i].nxt)
    {
        int y=e[i].to;
        if(e[i].flow>=e[i].w||col[y]==c)continue;
        getcol(y,c);
    }
}
inline void build(int l,int r)
{
    if(l==r)return;
    int x=a[l],y=a[l+1],w,L=l,R=r;
    w=Dinic(x,y);
    if(!mp.count(w))ans++,mp[w]=1;
    getcol(x,++tim);
    for(int i=l;i<=r;i++)
        if(col[a[i]]==tim)tmp[L++]=a[i];
        else tmp[R--]=a[i];
    L--,R++;
    for(int i=l;i<=r;i++)a[i]=tmp[i];
    build(l,L),build(R,r);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int u,v,w;scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);add(v,u,w);
    }
    for(int i=1;i<=n;i++)a[i]=i;
    build(1,n);
    printf("%d",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/nofind/p/12104017.html

时间: 2024-10-12 14:41:40

P4123 [CQOI2016]不同的最小割的相关文章

【BZOJ4519】[Cqoi2016]不同的最小割 最小割树

[BZOJ4519][Cqoi2016]不同的最小割 Description 学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割.对于带权图来说,将所有顶点处在不同部分的边的权值相加所得到的值定义为这个割的容量,而s,t的最小割指的是在关于s,t的割中容量最小的割.而对冲刺NOI竞赛的选手而言,求带权图中两点的最小割已经不是什么难事了.我们可以把视野放宽,考虑有N个点的无向连通图中所有点对的最

BZOJ4519: [Cqoi2016]不同的最小割

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

最小割树 - CQOI2016不同的最小割

最小割树 快速求无向图两点间的最小割 分治建立: 区间内任选两点\(x,y\),跑最小割,连边\((x,y,cut_{x,y})\) 根据此最小割,把点割成两部分,递归处理 新建出的树,两点路径上的最小值即为他们在原图上的最小割 时间复杂度\(O(n^3m)\),但网络流很难卡满 正确性证明 \(N850M8500\) 最小割树板题 #include<bits/stdc++.h> using namespace std; inline int read(){ int x=0,f=1;char

bzoj4519【CQOI2016】不同的最小割

4519: [Cqoi2016]不同的最小割 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 418  Solved: 254 [Submit][Status][Discuss] Description 学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成 两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割.对于带权图来说,将 所有顶点处在不同部分的边的权值相加所得到的值定义为这个割的容量,而s

【BZOJ-4519】不同的最小割 最小割树(分治+最小割)

4519: [Cqoi2016]不同的最小割 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 393  Solved: 239[Submit][Status][Discuss] Description 学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成 两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割.对于带权图来说,将 所有顶点处在不同部分的边的权值相加所得到的值定义为这个割的容量,而s,t

「CQOI2016」不同的最小割

「CQOI2016」不同的最小割 传送门 建出最小割树,把每一个点对的最小割抠出来 \(\text{unique}\) 一下就好了. 参考代码: #include <algorithm> #include <cstring> #include <cstdio> #define rg register #define file(x) freopen(x".in", "r", stdin), freopen(x".out&q

【BZOJ2039】【2009国家集训队】人员雇佣 [最小割]

人员雇佣 Time Limit: 20 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description 作为一个富有经营头脑的富翁,小L决定从本国最优秀的经理中雇佣一些来经营自己的公司.这些经理相互之间合作有一个贡献指数,(我们用Ei,j表示i经理对j经理的了解程度),即当经理i和经理j同时被雇佣时,经理i会对经理j做出贡献,使得所赚得的利润增加Ei,j.当然,雇佣每一个经理都需要花费一定的金钱Ai,对于一些经理可能他做出的贡献不值得

hdoj 4289 Control 【拆点 求最小割】

Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2295    Accepted Submission(s): 961 Problem Description You, the head of Department of Security, recently received a top-secret informati

There is a war (hdu 2435 最小割+枚举)

There is a war Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 970    Accepted Submission(s): 277 Problem Description There is a sea. There are N islands in the sea. There are some directional