hdu4289(最小割)

传送门:Control

题意:有n个城市,有个小偷想从其中一个城市逃到另一个城市,警察想要堵截这个小偷,知道了在每个城市堵截的成本,问如何安排在哪些城市堵截可以使得小偷一定会被抓住,而且成本最低。

分析:根据割的定义将整部图分成两部分且互不相通,这题明显是求最小割,根据最小割等于最大流,则拆点后直接求最大流即可,对于点值在最大流中的限制经常是拆点处理。

#pragma comment(linker,"/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <limits.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 100000000
#define inf 0x3f3f3f3f
#define eps 1e-6
#define N 100010
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define PII pair<int,int>
using namespace std;
inline int read()
{
    char ch=getchar();
    int x=0,f=1;
    while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch<=‘9‘&&ch>=‘0‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int n,m,vs,vt,tot,NV;
int head[N],gap[N],level[N],q[N];
struct edge
{
    int v,w,next;
    edge(){}
    edge(int v,int w,int next):v(v),w(w),next(next){}
}e[N<<1];
void addedge(int u,int v,int w)
{
    e[tot]=edge(v,w,head[u]);
    head[u]=tot++;
    e[tot]=edge(u,0,head[v]);
    head[v]=tot++;
}
void init()
{
    memset(head,-1,sizeof(head));
    tot=0;
}
/***************************SAP***********************/
void bfs(int vt)
{
    memset(level,-1,sizeof(level));
    memset(gap,0,sizeof(gap));
    level[vt]=0;
    gap[level[vt]]++;
    queue<int>que;
    que.push(vt);
    while(!que.empty()) {
        int u=que.front();
        que.pop();
        for(int i=head[u]; i!=-1; i=e[i].next) {
            int v=e[i].v;
            if(level[v]!=-1)continue;
            level[v]=level[u]+1;
            gap[level[v]]++;
            que.push(v);

        }
    }
}
int pre[N];
int cur[N];
int SAP()
{
    bfs(vt);
    memset(pre,-1,sizeof(pre));
    memcpy(cur,head,sizeof(head));
    int u=pre[vs]=vs,flow=0,aug=inf;
    gap[0]=NV;
    while(level[vs]<NV) {
        bool flag=false;
        for(int &i=cur[u]; i!=-1; i=e[i].next) {
            int v=e[i].v;
            if(e[i].w&&level[u]==level[v]+1) {
                flag=true;
                pre[v]=u;
                u=v;
                aug=min(aug,e[i].w);
                if(v==vt) {
                    flow+=aug;
                    for(u=pre[v]; v!=vs; v=u,u=pre[u]) {
                        e[cur[u]].w-=aug;
                        e[cur[u]^1].w+=aug;
                    }
                    aug=inf;
                }
                break;
            }
        }
        if(flag)continue;
        int minlevel=NV;
        for(int i=head[u]; i!=-1; i=e[i].next) {
            int v=e[i].v;
            if(e[i].w&&level[v]<minlevel) {
                minlevel=level[v];
                cur[u]=i;
            }
        }
        if(--gap[level[u]]==0)break;
        level[u]=minlevel+1;
        gap[level[u]]++;
        u=pre[u];
    }
    return flow;
}
/**************************SAP**********************/
int x,y;
void build()
{
    vs=read();vt=read()+n;NV=2*n+1;
    for(int i=1;i<=n;i++)
    {
        x=read();
        addedge(i,i+n,x);
        addedge(i+n,i,x);
    }
    for(int i=1;i<=m;i++)
    {
        x=read();y=read();
        addedge(x+n,y,inf);
        addedge(y+n,x,inf);
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)>0)
    {
        init();
        build();
        printf("%d\n",SAP());
    }
}

时间: 2024-10-20 12:42:04

hdu4289(最小割)的相关文章

HDU-4289 Control(最小割,拆点)

题目链接:HDU-4289 Control 题意 恐怖分子计划将武器从城市$S$运输到城市$D$,现在我们知道$S$和$D$,知道城市网络中存在的路径(无向边),知道封锁每个城市各自需要的代价,我们可以对任意城市进行封锁,恐怖分子到达被封锁的城市就会被抓捕,求抓捕所有恐怖分子需要的最小代价. 思路 显然这是一个最小割问题,但代价是点权而不是边权,所以需要对每个城市结点拆成入点和出点,入点向出点连边,边权为对应城市结点的点权,这样就将点权代价转换为边权代价.不同城市之间的双向路径$(u,v)$,$

hdu4289 Control --- 最小割,拆点

给一个无向图,告知敌人的起点和终点,你要在图上某些点安排士兵,使得敌人无论从哪条路走都必须经过士兵. 每个点安排士兵的花费不同,求最小花费. 分析: 题意可抽象为,求一些点,使得去掉这些点之后,图分成了两部分,敌人的起点和终点分别在这两部分里.即求最小割. 问题是最小割是边,这里把点拆成两个,自己到自己连边,边权为该点点权.其他题目给的边照连就可以了. 为了方便,对于点i,拆成(i,i+n). 因此,对于题目给的边(a,b),就连双向边边:(a+n,b,inf).(b+n,a,inf) #inc

hdu-4289.control(最小割 + 拆点)

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

网络流之最小割

最小割的相关知识请参见:网络流问题 I.     hdu4289    Control 题意:给出一个由n个点,m条边组成的无向图.给出两个点s,t.对于图中的每个点,去掉这个点都需要一定的花费.求至少多少花费才能使得s和t之间不连通. 分析:题意即求最小割,将每个点拆点,点与对应点的边权为去掉该点的花费,原图中所有边的边权赋为无穷大,跑一遍最大流即可.(最大流即最小割) 1 #include<iostream> 2 #include<cstdio> 3 #include<c

【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

HDU 3657 Game(取数 最小割)经典

Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1065    Accepted Submission(s): 449 Problem Description onmylove has invented a game on n × m grids. There is one positive integer on each g

POJ2914 Minimum Cut【全局最小割】【Stoer-Wangner】

题目链接: http://poj.org/problem?id=2914 题目大意: 提一个无向有重边的图,有重边的边权累加起来,求全局最小割. 思路: 一个无向连通图,去掉一个边集可以使其变成两个连通分量则这个边集就是割集.最小割 集当然就是权和最小的割集. 这是一个最简单的全局最小割模板题.直接套上模板就可以了.来说说Stoer-Wangner算 法吧. Stoer-Wangner算法: 对于图中的任意两个顶点u和v,若u,v属于最小割的同一个集合中,那么僵顶点u和顶点 v合并后并不影响图的