BZOJ 2229 最小割

谁会像我一样把INF设成0x3f?

GH Tree.

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxv 250
#define maxe 50050
#define inf 0x7fffffff
using namespace std;
struct edge
{
    int v,f,nxt;
}e[maxe];
int T,a,b,c,qq;
int n,m,map[maxv][maxv],f[maxv][maxv],s,t,nume,g[maxv];
int regis[maxv*maxv],cnt=0;
int dis[maxv],fath[maxv],rrr=0;
bool vis[maxv];
queue <int> q;
void reset()
{
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        {
            map[i][j]=0;
            f[i][j]=inf;
        }
}
void addedge(int u,int v,int w)
{
    e[++nume].v=v;
    e[nume].nxt=g[u];
    e[nume].f=w;
    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));
    vis[s]=true;q.push(s);
    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) && (!vis[v]))
            {
                dis[v]=dis[head]+1;
                vis[v]=true;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 ((dis[v]==dis[x]+1) && (e[i].f))
            {
                int dd=dinic(v,min(low,e[i].f));
                e[i].f-=dd;e[i^1].f+=dd;
                low-=dd;ret+=dd;
            }
        }
        if (!ret) dis[x]=0;
        return ret;
    }
}
int max_flow(int x,int y)
{
    s=x;t=y;
    int ans=0;
    while (bfs())
        ans+=dinic(s,inf);
    return ans;
}
void dfs(int x)
{
    vis[x]=true;
    for (int i=g[x];i;i=e[i].nxt)
    {
        int v=e[i].v;
        if ((!vis[v]) && (e[i].f))
            dfs(v);
    }
}
void Gusfield()
{
    for (int i=1;i<=n;i++) fath[i]=1;
    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()
{
    cnt=0;
    for (int i=1;i<=n;i++)
        for (int j=i+1;j<=n;j++)
            regis[++cnt]=f[i][j];
    sort(regis+1,regis+cnt+1);
    scanf("%d",&qq);
    for (int i=1;i<=qq;i++)
    {
        int tot=0;scanf("%d",&a);
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                if(f[i][j]<=a)tot++;
        printf("%d\n",tot);
    }
    printf("\n");
}
void work()
{
    scanf("%d%d",&n,&m);
    reset();
    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();
}
int main()
{
    scanf("%d",&T);
    for (int i=1;i<=T;i++)
        work();
    return 0;
}
时间: 2024-10-27 00:37:16

BZOJ 2229 最小割的相关文章

BZOJ 1797 最小割

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1797 题意:给出一个有向图,每条边有流量,给出源点汇点s.t.对于每条边,询问:(1)是否存在一个最小割包含该边?(2)是否所有的最小割都包含该边? 思路:首先求最大流,在残余网络中求强连通 分量.对于每条原图中的边(最大流中添加的反向边不算)<u,v>,该边的残余流量为0且u和v在两个不同的强连通分量中,则存在一个最小割 包含该边:在上述满足且u与s在一个连通分量.v与t在一个连通

bzoj 3996 最小割

公式推出来后想了半天没思路,居然A是01矩阵..... 如果一个问题是求最值,并那么尝试先将所有可能收益加起来,然后矛盾部分能否用最小割表达(本题有两个矛盾,第一个是选还是不选,第二个是i,j有一个不选,就不能获得bij的收益). 1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #define N 510 5 #define S N+N*N 6 #define E S*10 7 #define

BZOJ - 1497 最小割应用

题意:基站耗费成本,用户获得利益(前提是投入成本),求最大获利 最小割的简单应用,所有可能的收益-(消耗的成本/失去的收益),无穷大边表示冲突,最小割求括号内的范围即可 #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<string> #in

bzoj 3275 最小割

给你一堆东西,叫你选一些东西出来,使得价值最大,要求选出的东西集合中的任意a,b满足性质p. 可以考虑: 1.拟阵? 2.二分图? 这道题由于数学硬伤,不知道不存在两条直角边是奇数,斜边是整数的直角三角形. 证明是: 对于奇数a: a*a = 1 mod 4 对于偶数a: a*a = 0 mod 4 所以对于两个奇数a,b: a*a+b*b = 2 mod 4 不存在整数c使得: a*a+b*b = c*c mod 4 1 /***********************************

BZOJ 2229 ZJOI2011 最小割 最小割+分治 400AC达成&amp;&amp;2000Submission达成

题目大意:给定一个图,多次询问有多少个点对之间的最小割小于等于某个值 最小割分治- - 首先朴素的想法是做O(n^2)遍网络流 但是这样显然是过不去的 根据一些结论,最小割最多有n-1个,这n-1个最小割构成一个最小割树 别问我为什么- - 因此我们分治寻找这n-1个最小割 每层分治,先任选两个点作为源汇做一遍最小割 然后找出S集和T集,对所有S集的点和T集的点构成的点对用本次得到的最小割更新一遍 注意更新的是全部S集和全部T集,不只是本次分治内部的S集和T集 然后将本次分治的点分成S集和T集,

BZOJ 1266 上学路线route(最小割)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1266 题意:给出一个无向图,每条边有长度和代价.求出1到n的最短路.之后删掉一些边使得1到n的最短路变大?在此情况下使得删掉边的代价之和最小. 思路:首先求出每个点到1和n的最短路.之后可以确定每条边是否为关键边(就是最短路上的边).将关键边建立网络流图,求最小割即可. struct node { int v,cap,next; }; node edges[N]; int head[N

BZOJ 2007 海拔(平面图最小割-最短路)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2007 题意:给出一个n*n的格子,那么顶点显然有(n+1)*(n+1)个.每两个相邻顶点之间有两条边,这两条边是有向的,边上有权值..左上角为源点,右下角为汇点,求s到t的最小割. 思路:很明显这是一个平面图,将其转化为最 短路.我们将s到t之间连一条边,左下角为新图的源点S,右上角区域为新图的终点T,并且为每个格子编号.由于边是有向的,我们就要分析下这条边应该是哪 个点向哪个点的边.

BZOJ 1976 能量魔方 Cube(最小割)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1976 题意:给出一个n*n*n的立方体.每个小单位为字母P或者字母N.相邻两个小单位字母不同则总价值加1.现在有些小单位的字母已经确定,合理安排其他小单位的字母使得总价值最大? 思路:显然,若所有小单位都未确定,则进 行黑白染色即PN相间的安排时价值最大.基于这样的考虑,我们将所有小单位分成黑白两种颜色,设为A和B.显然同一种颜色之间是不会相邻的.设S集合为A 集合中的P(就是已经给出

BZOJ 2132 圈地计划(最小割)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2132 题意:n*m的格子染色黑白,对于格子(i,j)染黑色则价值为A[i][j],白色为B[i][j].若一个格子四周不同颜色的有x个,则额外的价值为x*C[i][j].求最大价值. 思路:将格子黑白染色分成两个集合X和Y.S集合为X中的A和Y中的B,T为X中的B和Y中的A.相邻的连边为两个格子的C值之和.总权值减去最小割即是答案. struct node { int v,cap,ne