Barricade---hdu5889(最短路+网络流)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5889

题意:有n个点m条边,每条边的长度相同,我们可以默认为1,构成一个无向图;现在起点为1,终点为n,从起点到终点有很多路可走,现在已知每次走的都是最短路径;

现在要设置障碍,已知在每条边上设置障碍的代价wi, 为了让从起点到达终点一定能看到至少一个障碍,求建立障碍的最小代价;

思路:已知每次都会选择最短路径,所以我们可以把所有的最短路径所包含的边都找出来建立新的网络流图,然后求从起点到达终点的网络流即可;

参考题目hdu3416:http://www.cnblogs.com/zhengguiping--9876/p/5829830.html

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<set>
using namespace std;
#define met(a, b) memset(a, b, sizeof(a))
#define N 100005
#define INF 0x3f3f3f3f
typedef long long LL;

struct node
{
    int v, w, d, Next;
    node(int v_=0, int w_=0, int d_=0) : v(v_), w(w_), d(d_){}
}e[N*4];

vector<vector<node> >g;///存放原图;
int n, vis[N];
int dist[N];///spfa中的从起点到i的最短距离;
int l[N];///Dinic中的分层

int Head1[N], cnt1;
void Add1(int u, int v, int w)///添加新的边;
{
    e[cnt1].v = v;
    e[cnt1].w = w;
    e[cnt1].Next = Head1[u];
    Head1[u] = cnt1++;
}

void Init()
{
    g.clear();
    g.resize(n+1);
    met(Head1, -1);
    cnt1 = 0;
    for(int i=0; i<=n; i++)
    {
        vis[i] = 0;
        dist[i] = INF;
    }
}

void spfa()
{
    dist[1] = 0;
    vis[1] = 1;
    queue<int>Q;
    Q.push(1);
    while(!Q.empty())
    {
        int p = Q.front();Q.pop();
        vis[p] = 0;
        for(int i=0, len=g[p].size(); i<len; i++)
        {
            int q = g[p][i].v;
            if(dist[q] > dist[p]+g[p][i].d)
            {
                dist[q] =  dist[p]+g[p][i].d;
                if(!vis[q])
                {
                    vis[q] = 1;
                    Q.push(q);
                }
            }
        }
    }
}

bool bfs(int s, int End)
{
    met(l, 0);
    queue<int>Q;
    Q.push(s);
    l[s] = 1;
    while(!Q.empty())
    {
        int u = Q.front();Q.pop();
        if(u == End) return true;
        for(int i=Head1[u]; i!=-1; i=e[i].Next)
        {
            int v = e[i].v;
            if(!l[v] && e[i].w)
            {
                l[v] = l[u]+1;
                Q.push(v);
            }
        }
    }
    return false;
}

int dfs(int u, int MaxFlow, int End)
{
    if(u == End)return MaxFlow;

    int uflow = 0;

    for(int j=Head1[u]; j!=-1; j=e[j].Next)
    {
        int v = e[j].v;
        if(l[v]==l[u]+1 && e[j].w)
        {
            int flow = min(e[j].w, MaxFlow-uflow);
            flow = dfs(v, flow, End);
            e[j].w -= flow;
            e[j^1].w += flow;
            uflow += flow;
            if(uflow == MaxFlow)
                break;
        }
    }
    if(uflow == 0)
        l[u] = 0;
    return uflow;
}

int Dinic()
{
    int MaxFlow = 0;
    while(bfs(1, n))
        MaxFlow += dfs(1, INF, n);
    return MaxFlow;
}

int main()
{
    int T, m, u, w, v;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d %d", &n, &m);

        Init();

        for(int i=1; i<=m; i++)
        {
            scanf("%d %d %d", &u, &v, &w);
            g[u].push_back(node(v, w, 1));
            g[v].push_back(node(u, w, 1));
        }

        spfa();///更新dist

        for(int i=1; i<=n; i++)
        {
            for(int j=0, len=g[i].size(); j<len; j++)
            {
                int p = g[i][j].v;
                if(dist[p] == dist[i] + g[i][j].d)///说明从点i到达点p的路在最短路径上;
                {
                    Add1(i, p, g[i][j].w);///建立新图;
                    Add1(p, i, 0);///注意这里是0;
                }
            }
        }

        int ans = Dinic();///求最大流即可;

        printf("%d\n", ans);
    }
    return 0;
}

时间: 2024-11-10 14:13:19

Barricade---hdu5889(最短路+网络流)的相关文章

HDU 5889 (最短路+网络流)

Barricade Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1117    Accepted Submission(s): 340 Problem Description The empire is under attack again. The general of empire is planning to defend hi

POJ 2391Ombrophobic Bovines(二分+最短路+网络流之最大流)

题目地址:http://poj.org/problem?id=2391 这个题WA了一晚上,原因是数组开小了,然后又TLE了一天,原因是数组改的过大了....不多说什么了... 思路不难,建图也不难,二分时间,然后把每个田地之间的最短距离用floyd最短路求出来.然后建立一个源点与汇点,将田地拆分成两个点,在距离之内的进行连边,要单向连边.然后将源点与田地相连,权值为每个田地的牛的数目,再把另一边的田地与汇点相连,权值为每个田地最大可避雨的牛的数目.拆开的田地之间权值可以为无穷大. 代码如下:

POJ2112Optimal Milking(二分+floyd最短路+网络流)

题目地址:http://poj.org/problem?id=2112 最近忙着预习课本备考,没怎么刷题,(我是真的有在好好看书..)不敲题还是手痒痒,马上就邀请赛了,还是每晚睡觉前都拿来刷题吧.白天的时间足够了. 话说这题调了一晚上...一直以为是几天没敲状态下滑..(虽然也没几天..)当发现错误的时候才发现原来是少敲了个字母...而且我一般很少在bfs的那个地方出错,错误地方也很隐蔽..所以找了一晚上,真是敲错一个字母成千古恨. 这题大概是职业生涯目前为止敲得最长的一道算法题了..(模拟题除

HDU 3416 Marriage Match IV(最短路+网络流之最大流)

题目地址:HDU 3416 这道题WA了一天半...最终才发现是我一直习惯性的将isap的表示上界的变量直接表示成sink+1了...但是在这道题里汇点sink不一定是最后一个点...sad... 这题可以有两种方法做,一种是求两次最短路,d1表示所有点到源点的最短距离,再求一次用d2表示所有点到汇点的最短距离.然后根据公式d1[u]+d2[v]+w==d1[sink]判断是否属于最短路中的一条边. 还有一种是只求一次最短路,直接用d[v]==d[u]+w来判断是否是可以到达源点的最短路,如果可

HDU5889 Barricade(最短路)(网络流)

Barricade Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 604    Accepted Submission(s): 172 Problem Description The empire is under attack again. The general of empire is planning to defend his

hdu3416 Marriage Match IV(最短路+网络流)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416 题意: 给出含n个点.m条有向边的图,每条边只能走一次,给出起点和终点,求起点到终点的最短路径有多少条. 思路: 题目要求是最短路径,当然需要求出最短路,用Dijkstra就可以了,然后我们需要构造网络流的图.将能组成最短路的边加入图中,容量设为1,注意能组成最短路的边是满足dis[u] + edge[i].dist == dis[v] 的边,其中u是边的起点,v是边的终点,dis[]保存的是

bzoj 3931: [CQOI2015]网络吞吐量(最短路+网络流)

3931: [CQOI2015]网络吞吐量 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 1194  Solved: 508 [Submit][Status][Discuss] Description 路由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点.网络中实现路由转发的硬件设备称为路由器.为了使数据包最快的到达目的地,路由器需要选择最优的路径转发数据包.例如在常用的路由算法OSPF(开放式最短路径优先

HDU 5889 Barricade(最短路+最小割)

http://acm.hdu.edu.cn/showproblem.php?pid=5889 题意: 给出一个图,帝国将军位于1处,敌军位于n处,敌军会选择最短路到达1点.现在帝国将军要在路径上放置障碍,每条边上都有一个放置障碍的代价.求至少需要多少代价. 思路: 首先就是求最短路,然后将最短路上的边重新进行构图跑最小割即可. 一开始求了两遍bfs,分别求出起点到各个点的距离和终点到各个点的距离,然后去判断每条边是否在最短路中,但是这样的话在最大流的构图中无法确定方向,然后就一直Wa... 其实

【BZOJ3931】【CQOI2015】网络吞吐量 最短路+网络流

链接: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44922137"); } 题解: --两遍最短路然后判断哪些边可以在某条最短路上,然后加到网络流图中. 然后题意是一个点经过流量有限制,拆点就好. 然后有重边Qwq(调了好久...) 然后或许有自环,不过这并不影响什么. 代码: 调试