BZOJ 4519 不同的最小割

GH树。。。好像无向图上跑DINIC要慢一点。

反正能过就是了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxe 200050
#define maxv 1050
const int inf=0x7fffffff/2;
using namespace std;
struct edge
{
    int v,f,nxt;
}e[maxe];
int n,m,a,b,c,g[maxv],fath[maxv],f[maxv][maxv];
int map[maxv][maxv],nume,s,t;
int dis[maxv],regis[800500];
bool vis[maxv];
queue <int> q;
void addedge(int u,int v,int f)
{
    e[++nume].v=v;
    e[nume].f=f;
    e[nume].nxt=g[u];
    g[u]=nume;
    e[++nume].v=u;
    e[nume].f=0;
    e[nume].nxt=g[v];
    g[v]=nume;
}
void build()
{
    nume=1;memset(g,0,sizeof(g));
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        {
            if (map[i][j])    addedge(i,j,map[i][j]);
        }
}
bool bfs()
{
    while (!q.empty()) q.pop();
    memset(dis,0,sizeof(dis));
    memset(vis,false,sizeof(vis));
    q.push(s);dis[s]=0;vis[s]=true;
    while (!q.empty())
    {
        int head=q.front();
        q.pop();
        for (int i=g[head];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if ((e[i].f>0) && (!vis[v]))
            {
                vis[v]=true;
                dis[v]=dis[head]+1;
                q.push(v);
            }
        }
    }
    return dis[t]>0;
}
int dinic(int x,int low)
{
    if (x==t) return low;
    else
    {
        int ret=0;
        for (int i=g[x];low && i;i=e[i].nxt)
        {
            int v=e[i].v;
            if ((e[i].f>0) && (dis[v]==dis[x]+1))
            {
                int dd=dinic(v,min(low,e[i].f));
                ret+=dd;low-=dd;
                e[i].f-=dd;e[i^1].f+=dd;
            }
        }
        if (!ret) dis[x]=0;
        return ret;
    }
}
int max_flow(int x,int y)
{
    s=x;t=y;
    int now=0;
     while (bfs())
        now+=dinic(s,inf);
    return now;
}
void dfs(int now)
{
    vis[now]=true;
    for (int i=g[now];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if ((e[i].f>0) && (!vis[v])) dfs(v);
    }
}
void Gusfield()
{
    for (int i=1;i<=n;i++) fath[i]=1;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            f[i][j]=inf;
    for (int i=2;i<=n;i++)
    {
        build();
        int maxf=max_flow(fath[i],i);
        memset(vis,false,sizeof(vis));
        dfs(fath[i]);
        for (int j=1;j<i;j++)
            f[i][j]=f[j][i]=min(f[j][fath[i]],maxf);
        for (int j=i+1;j<=n;j++)
        {
            if ((fath[i]==fath[j]) && (!vis[j]))
                fath[j]=i;
        }
    }
}
void get_ans()
{
    int cnt=0;
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=n;j++)
        {
            if (f[i][j]!=inf)
                regis[++cnt]=f[i][j];
        }
    }
    sort(regis+1,regis+cnt+1);
    int ans=unique(regis+1,regis+cnt+1)-regis-1;
    printf("%d\n",ans);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        map[a][b]+=c;map[b][a]+=c;
    }
    Gusfield();
    get_ans();
    return 0;
} 
时间: 2024-08-30 06:00:30

BZOJ 4519 不同的最小割的相关文章

bzoj 1497 最大获利 - 最小割

新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU集团旗下的CS&T通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成前期市场研究.站址勘测.最优化等项目.在前期市场调查和站址勘测之后,公司得到了一共N个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第i个通讯中转站需要的成本为Pi(1≤i≤N).另外公司调查得出了所有期望中的

[BZOJ 2127] happiness 【最小割】

题目链接:BZOJ - 2127 题目分析 首先,每个人要么学文科,要么学理科,所以可以想到是一个最小割模型. 我们就确定一个人如果和 S 相连就是学文,如果和 T 相连就是学理. 那么我们再来确定建图.首先使用最小割,就是先加上所有可能获得的权值,再减去最小割(即不能获得的权值). 如果一个人学理,就要割掉与 S 相连的边,那么就是要割掉学文的收益.于是,对于每个点,从 S 向它连边,权值为它学文的收益. 同理,对于每个点,从它向 T 连边,权值为它学理的收益. 对于两个相邻的人,他们有同时学

BZOJ 2561 最小生成树 | 网络流 最小割

链接 BZOJ 2561 题解 用Kruskal算法的思路来考虑,边(u, v, L)可能出现在最小生成树上,就是说对于所有边权小于L的边,u和v不能连通,即求最小割: 对于最大生成树的情况也一样.容易看出两个子问题是各自独立的,把两个最小割相加即可. #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <queue> using

bzoj 1797: [Ahoi2009]Mincut 最小割

求最小割的可行边与必须边,先求一遍最大流,然后在残量网络上求强连通分量,对于可行边 起始点与结束点要在不同的强连通分量里,对于必须边 起始点要与S在一个SCC里 结束点要与T在一个SCC里. 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<queue> 7 #incl

bzoj 4439: [Swerc2015]Landscaping -- 最小割

4439: [Swerc2015]Landscaping Time Limit: 2 Sec  Memory Limit: 512 MB Description FJ有一块N*M的矩形田地,有两种地形高地(用‘#’表示)和低地(用‘.’表示) FJ需要对每一行田地从左到右完整开收割机走到头,再对每一列从上到下完整走到头,如下图所示 对于一个4*4的田地,FJ需要走8次. 收割机是要油的,每次从高地到低地或从低地到高地需要支付A的费用. 但是FJ有黑科技,可以高地与低地的互变,都只需要一个支付B的

BZOJ 1391: [Ceoi2008]order [最小割]

1391: [Ceoi2008]order Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1509  Solved: 460[Submit][Status][Discuss] Description 有N个工作,M种机器,每种机器你可以租或者买过来. 每个工作包括若干道工序,每道工序需要某种机器来完成,你可以通过购买或租用机器来完成. 现在给出这些参数,求最大利润 Input 第一行给出 N,M(1<=N<=1200,1<=M<=12

bzoj 3158 千钧一发(最小割)

3158: 千钧一发 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 767  Solved: 290[Submit][Status][Discuss] Description Input 第一行一个正整数N. 第二行共包括N个正整数,第 个正整数表示Ai. 第三行共包括N个正整数,第 个正整数表示Bi. Output 共一行,包括一个正整数,表示在合法的选择条件下,可以获得的能量值总和的最大值. Sample Input 4 3 4 5 12 9

bzoj 3144: [Hnoi2013]切糕 最小割

3144: [Hnoi2013]切糕 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 681  Solved: 375[Submit][Status] Description Input 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤P, 1≤y≤Q, 1≤z≤R). 100%的数据满足P,Q,R≤40,0≤D≤

BZOJ 1797: [Ahoi2009]Mincut 最小割( 网络流 )

先跑网络流, 然后在残余网络tarjan缩点. 考虑一条边(u,v): 当且仅当scc[u] != scc[v], (u,v)可能出现在最小割中...然而我并不会证明 当且仅当scc[u] = scc[S] && scc[v] == scc[T], (u, v) 必定出现在最小割中. 这个很好脑补, 假如这条边不是满流, 那么S-T就存在增广路了.. ----------------------------------------------------------------------