vijos 1524 最小监视代价

背景

看到Vijos上此类型的题目较少,特地放一道上来给大家练练。

描述

由于yxy小朋友做了一些不该做的事,他被jzp关进了一个迷宫里。由于jzp最近比较忙,疏忽大意了一些,yxy可以在迷宫中任意走动。整个迷宫可以被看作是一个无向图。迷宫中有一些结点有传送点,可以让他逃离这个迷宫。jzp发明了一种机器人,可以监视迷宫中的道路,被监视的道路yxy不能通过,我们简单的认为监视一条道路的代价即为这条道路的长度。现在jzp正在忙,请你编一个程序算出使yxy无法逃离迷宫的最小监控总代价。(yxy一开始在1号结点)

格式

输入格式

第1行:两个自然数n和e,分别表示迷宫的节点数和边数。

第2至e+1行:每行三个自然数a、b和w,表示a和b之间有一条道路,长度为w。

第e+2行:一个自然数m,表示有传送点结点的个数。

第e+3行:m个自然数,表示有传送点的结点。

输出格式

一个自然数,表示最小监视总代价。

样例1

样例输入1

5 5
1 2 1
1 3 2
2 5 3
2 3 3
3 4 2
2
4 5

样例输出1

3

限制

每个测试点1s

提示

n<100,e<300,m<n
1<=a,b<=n
w<=maxint

来源

经典问题改编

最大流

屠龙宝刀点击就送

#include <cstring>
#include <cstdio>
#include <queue>
#define inf 1e9
#define Max 150

using namespace std;
struct node
{
    int next,to,dis;
}edge[Max*Max];
int Answer,head[Max*Max],cnt=1,n,m,e,dep[Max*Max];
void add(int u,int v,int l)
{
    node*w=&edge[++cnt];
    w->next=head[u];
    w->to=v;
    w->dis=l;
    head[u]=cnt;
}
bool bfs(int s,int t)
{
    for(int i=1;i<=n;++i) dep[i]=inf;
    dep[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int tp=q.front();
        q.pop();
        for(int i=head[tp];i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dep[v]>dep[tp]+1&&edge[i].dis)
            {
                dep[v]=dep[tp]+1;
                if(v==t) return 1;
                q.push(v);
            }
        }
    }
    return 0;
}
int dfs(int s,int t,int came_flow)
{
    if(s==t||came_flow==0) return came_flow;
    int res=0,f;
    for(int i=head[s];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(dep[v]==dep[s]+1&&edge[i].dis&&(f=dfs(v,t,min(came_flow,edge[i].dis))))
        {
            res+=f;
            came_flow-=f;
            edge[i].dis-=f;
            edge[i^1].dis+=f;
        }
        if(came_flow==0) break;
    }
    return res;
}
int dinic(int s,int t)
{
    while(bfs(s,t)) Answer+=dfs(s,t,inf);
    return Answer;
}
int main()
{
    scanf("%d%d",&n,&e);
    for(int x,y,z;e--;)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
        add(y,x,z);
    }
    scanf("%d",&m);
    for(int x;m--;)
    {
        scanf("%d",&x);
        add(x,n,inf);
        add(n,x,inf);
    }
    printf("%d",dinic(1,n));
    return 0;
}
时间: 2024-10-10 20:09:20

vijos 1524 最小监视代价的相关文章

[Vijos P1524]最小监视代价

题目大意:有一些点和一些边,每条边有一个监视代价.一个人从1号点出发,到达某些“传送点”可以逃生.但被监视的边就不能走了.要你用最小的监视代价使得那个人无法传送. 解题思路:求最小割.先建一个超级汇点$n+1$,把所有传送点连上这个超级汇点,然后根据“最小割=最大流”的定理,跑最大流即可.注意无向图. 以下为Dinic算法代码. C++ Code: #include<cstdio> #include<vector> #include<cstring> #include&

vijos - P1456最小总代价 (状态压缩DP + 记忆化搜索)

P1456最小总代价 Accepted 标签:[显示标签] 描述 n个人在做传递物品的游戏,编号为1-n. 游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位:下一个人可以传递给未接过物品的任意一人. 即物品只能经过同一个人一次,而且每次传递过程都有一个代价:不同的人传给不同的人的代价值之间没有联系: 求当物品经过所有n个人后,整个过程的总代价是多少. 格式 输入格式 第一行为n,表示共有n个人(16>=n>=2): 以下为n*n的矩阵,第i+1行.第j列表示物

【网络流24题】 No.12 软件补丁问题(最小转移代价 最短路)

[题意] T 公司发现其研制的一个软件中有 n 个错误, 随即为该软件发放了一批共 m 个补丁程序. 每一个补丁程序都有其特定的适用环境, 某个补丁只有在软件中包含某些错误而同时又不包含另一些错误时才可以使用.一个补丁在排除某些错误的同时, 往往会加入另一些错误.换句话说, 对于每一个补丁 i, 都有 2 个与之相应的错误集合 B1[i]和 B2[i],使得仅当软件包含 B1[i]中的所有错误, 而不包含 B2[i]中的任何错误时, 才可以使用补丁 i. 补丁 i 将修复软件中的某些错误 F1[

最小编辑代价

最小编辑代价问题: 对于两个字符串A和B,我们需要进行插入.删除和修改操作将A串变为B串,定义c0,c1,c2分别为三种操作的代价,请设计一个高效算法,求出将A串变为B串所需要的最少代价. 给定两个字符串A和B,及它们的长度和三种操作代价,请返回将A串变为B串所需要的最小代价.保证两串长度均小于等于300,且三种代价值均小于等于100. 测试样例: "abc",3,"adc",3,5,3,100 返回:8 问题分析:看到这道题,首先想到的是编辑距离问题,可以说是有异

hdu 3315 My Brute 费用流,费用最小且代价最小

很常见的想法了= = #include <stdio.h> #include <iostream> #include <string.h> using namespace std; const int N=400; const int MAXE=200000; const int inf=1<<30; int head[N],s,t,cnt,n,m,ans; int d[N],pre[N]; bool vis[N]; int q[MAXE]; int V[N

最小调整代价-lintcode(c++)

lintcode91:最小调整代价给一个整数数组,调整每个数的大小,使得相邻的两个数的差不大于一个给定的整数target,调整每个数的代价为调整前后的差的绝对值,求调整代价之和最小是多少.例如:对于数组[1, 4, 2, 3]和target=1,最小的调整方案是调整为[2, 3, 2, 3],调整代价之和是2.返回2.例如:对于数组[1, 5, 6]和target=1,最小的调整方案为[4,5,6],调整代价之和是3.返回3. 思路分析:如何去构造最优子结构?如何存放数据?对于这些问题,我想了一

最小总代价 状压DP

描述 n个人在做传递物品的游戏,编号为1-n. 游戏规则是这样的:开始时物品可以在任意一人手上,他可把物品传递给其他人中的任意一位:下一个人可以传递给未接过物品的任意一人. 即物品只能经过同一个人一次,而且每次传递过程都有一个代价:不同的人传给不同的人的代价值之间没有联系:求当物品经过所有n个人后,整个过程的总代价是多少. 格式 输入格式 第一行为n,表示共有n个人(16>=n>=2):以下为n*n的矩阵,第i+1行.第j列表示物品从编号为i的人传递到编号为j的人所花费的代价,特别的有第i+1

最小编辑代价-golang

题目: 给定两个字符串str1和str2,在给定三个整数ic,dc和rc,分别代表插入.删除和替换一个 字符,返回将str1编辑成str2的最小代价. 解题方法: 动态规划.首先生成大小为(M+1)X(N+1)的矩阵dp. 假设str1="av=b12cd3", str2="abcdf".dp[i][j]表示str1[0:i]编辑成str2[0:j]的最小代价.计算结果如下: 计算步骤: 1.dp[0][0]表示str1空的子串编辑成str2空的子串的代价为0 2.

动态规划 最小编辑代价

题目描述: 给定两个字符串str1和str2,再给定三个整数ic,dc,rc,分别代表插入.删除.替换一个字符的代价,返回将str1编辑成str2的最小代价.举例:str1="abc"   str2="adc"  ic=5    dc=3   rc=2,从"abc"编辑到"adc"把b替换成d代价最小,为2:str1="abc"   str2="adc"  ic=5    dc=3