hdu4289 Control --- 最小割,拆点

给一个无向图,告知敌人的起点和终点,你要在图上某些点安排士兵,使得敌人无论从哪条路走都必须经过士兵。

每个点安排士兵的花费不同,求最小花费。

分析:

题意可抽象为,求一些点,使得去掉这些点之后,图分成了两部分,敌人的起点和终点分别在这两部分里。即求最小割。

问题是最小割是边,这里把点拆成两个,自己到自己连边,边权为该点点权。其他题目给的边照连就可以了。

为了方便,对于点i,拆成(i,i+n)。

因此,对于题目给的边(a,b),就连双向边边:(a+n,b,inf)、(b+n,a,inf)

#include<cstdio>
#include<vector>
#include<cstring>
#include<queue>
#define maxn 410
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
    int from,to,cap,flow;
};
struct dinic
{
    int n,m,s,t;
    vector<node> e;
    vector<int> g[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn];

    void init(int n)
    {
        e.clear();
        for(int i=0;i<=n+2;i++)
            g[i].clear();
    }

    void addedge(int a,int b,int c,int d)
    {
        e.push_back((node){a,b,c,0});
        e.push_back((node){b,a,d,0});
        m=e.size();
        g[a].push_back(m-2);
        g[b].push_back(m-1);
    }

    bool bfs()
    {
        memset(vis,0,sizeof vis);
        queue<int> q;
        q.push(s);
        d[s]=0;
        vis[s]=1;
        while(!q.empty())
        {
            int x=q.front();q.pop();
            for(int i=0;i<g[x].size();i++)
            {
                node& ee=e[g[x][i]];
                if(!vis[ee.to]&&ee.cap>ee.flow)
                {
                    vis[ee.to]=1;
                    d[ee.to]=d[x]+1;
                    q.push(ee.to);
                }
            }
        }
        return vis[t];
    }

    int dfs(int x,int a)
    {
        if(x==t||a==0) return a;
        int flow=0,f;
        for(int& i=cur[x];i<g[x].size();i++)
        {
            node& ee=e[g[x][i]];
            if(d[x]+1==d[ee.to]&&(f=dfs(ee.to,min(a,ee.cap-ee.flow)))>0)
            {
                ee.flow+=f;
                e[g[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0) break;
            }
        }
        return flow;
    }

    int maxflow(int s,int t)
    {
        this->s=s;
        this->t=t;
        int flow=0;
        while(bfs())
        {
            memset(cur,0,sizeof cur);
            flow+=dfs(s,inf);
        }
        return flow;
    }
};
dinic solve;

int main()
{
    int i,a,b,st,en,n,m;
    while(~scanf("%d%d",&n,&m))
    {
        scanf("%d%d",&st,&en);
        solve.init(n+n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a);
            solve.addedge(i,i+n,a,0);
        }
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            solve.addedge(a+n,b,inf,0);
            solve.addedge(b+n,a,inf,0);
        }
        printf("%d\n",solve.maxflow(st,en+n));
    }
    return 0;
}
时间: 2024-10-19 12:01:01

hdu4289 Control --- 最小割,拆点的相关文章

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

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

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

poj 1815 Friendship (最小割+拆点+枚举)

题意: 就在一个给定的无向图中至少应该去掉几个顶点才能使得s和t不联通. 算法: 如果s和t直接相连输出no answer. 把每个点拆成两个点v和v'',这两个点之间连一条权值为1的边(残余容量) v和v''分别是一个流进的点,一个流出的点. 根据求最小割的性质,权值小的边是可能被选择的(断开的). 添加源点st=0和汇点en=2*n+1,源点与s连权值为inf的边,t''与汇点连权值为inf的边. s与s'',t与t''连权值为inf的边,这样保证自己和自己是不会失去联系的. 如果i和j有边

hdu 4289 Control(最小割 + 拆点)

http://acm.hdu.edu.cn/showproblem.php?pid=4289 Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2247    Accepted Submission(s): 940 Problem Description You, the head of Department of Secu

HDU 4289 Control (最小割 拆点)

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

HDU 4289 Control 最小割

Control 题意:有一个犯罪集团要贩卖大规模杀伤武器,从s城运输到t城,现在你是一个特殊部门的长官,可以在城市中布置眼线,但是布施眼线需要花钱,现在问至少要花费多少能使得你及时阻止他们的运输. 题解:裸的最小割模型,最小割就是最大流,我们把点拆成2个点,然后将原点与拆点建边,流量为在城市建立眼线的费用,然后拆点为出点,原点为入点,将可以到达的城市之间建流量为无穷的边. 最后求出s 到 t的拆点的最大流 那么就是这个题目的答案了. 代码: 1 #include<bits/stdc++.h>

hdoj 3820 Golden Eggs 【最小割+拆点】

题目:hdoj 3820 Golden Eggs 题意:给出一个矩阵,然后当前有三种选择,放一个金蛋,放一个银蛋,或者不放,然后给出每个格子放金蛋或者银蛋的得分,如果金蛋相邻的话每个得分要减掉cost1,银蛋相邻的话每个减去cost2得分,问最大得分多少? 分析:做这个题目推荐先做hdoj 1659 ,3657点击打开链接 ,这个题目相当于前两个的融合在加点变化. 首先我们发现和前两个题目一样要求不能相邻,否则要减去一定的值,那么我们可以确定同样要用当前点的行列和的奇偶性建图. 那么我们可以按照

hdoj 3491 Thieves 【最小割 + 拆点】

题目:hdoj 3491 Thieves 题意:给出一个无向图,然后有个出发城市s,结束城市 t ,然后每个点有流量限制,问你最少用多少的人能够使得 s 到 t 没有流量. 分析:题意是抽象出来的,但是很明显看出来是求最小割.难点有2 1:无向图,所以要建双向边 2:点有流量限制,所以要拆点,拆成两个点,然后这两点的容量为点的限制,图中点的连接设置流量为inf,保证割不掉,只能从点之间割. AC代码: #include <cstdio> #include <cstring> #in

HDU - 4289 Control (最小割 MCMF)

题目大意:有一个间谍要将一些机密文件送到目的地 现在给出间谍的初始位置和要去的目的地,要求你在间谍的必经路上将其拦获且费用最小 解题思路:最小割最大流的应用,具体可以看网络流–最小割最大流 建图的话 超级源点–起始城市,容量为INF 城市拆成两点(u, v),容量为监视该城市的代价 能连通的城市连接,容量为INF 目的地和超级汇点相连,容量为INF #include <cstdio> #include <cstring> #include <algorithm> #in