因为C是不断变化的而且C是和点权相关和边权无关 所以我们可以MCMF但是MCMF的时候不能与C相关

再分析问题 我们可以认为每条路径S->T只覆盖T这个终点 因为题目中说了如果Si != Ti 要多付出 C的代价

假设我们走过的路径形成了一个环则刚好 边数=点数 覆盖完了

如果走过的路径不是一个环 则还有起点没有覆盖 此时我们可以把它当作没有途径的城市 给他补偿 同样为C

所以我们把原图拆成左边出点 右边入点 传递闭包后建图

这样每次MCMF增广的代价是不递减的 并且每增广一次多覆盖一个点 所以我们把每次增广的代价放到一个数组里面

每次询问我们二分C在数组里的位置,在C之前的点我们利用路径覆盖 在C及C之后的点我们用C去补偿它

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAX 255
inline int read() {
int x = ;
bool t = false;
char ch = getchar();
while ((ch < '' || ch > '') && ch != '-')
ch = getchar();
if (ch == '-')
t = true, ch = getchar();
while (ch <= '' && ch >= '')
x = x * + ch - , ch = getchar();
return t ? -x : x;
}
int val[MAX], sum[MAX], tot;
namespace MCMF {
const int MAXM = , MAXN = ;
struct Line {
int v, next, w, fy;
} e[MAXM];
int h[MAXN], cnt = ;
inline void Add(int u, int v, int w, int fy) {
e[cnt] = (Line) {
v, h[u], w, fy
};
h[u] = cnt++;
e[cnt] = (Line) {
u, h[v], , -fy
};
h[v] = cnt++;
}
int dis[MAXN], pe[MAXN], pv[MAXN], Cost, Flow;
bool vis[MAXN];
queue<int> Q;
int S = , T = MAXN - ;
bool SPFA() {
memset(dis, , sizeof(dis));
dis[S] = ;
Q.push(S);
vis[S] = true;
while (!Q.empty()) {
int u = Q.front();
Q.pop();
for (int i = h[u]; i; i = e[i].next) {
int v = e[i].v;
if (!e[i].w)
continue;
if (dis[u] + e[i].fy < dis[v]) {
dis[v] = dis[u] + e[i].fy;
pe[v] = i, pv[v] = u;
if (!vis[v])
vis[v] = true, Q.push(v);
}
}
vis[u] = false;
}
if (dis[T] >= 1e9)
return false;
int flow = 1e9;
for (int i = T; i != S; i = pv[i])
flow = min(flow, e[pe[i]].w);
for (int i = T; i != S; i = pv[i])
e[pe[i]].w -= flow, e[pe[i] ^ ].w += flow;
Flow += flow;
Cost += dis[T] * flow;
val[++tot] = dis[T] * flow;
sum[tot] = sum[tot - ] + val[tot];
return true;
}
}
using namespace MCMF;
int n, m, q, g[MAX][MAX];
int main() {
n = read();
m = read();
q = read();
memset(g, , sizeof(g));
for (int i = ; i <= n; ++i)
g[i][i] = ;
for (int i = , u, v; i <= m; ++i)
u = read(), v = read(), g[u][v] = min(read(), g[u][v]);
for (int k = ; k <= n; ++k)
for (int i = ; i <= n; ++i)
for (int j = ; j <= n; ++j)
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
for (int i = ; i <= n; ++i)
for (int j = ; j <= n; ++j)
if (i ^ j)
Add(i, j + n, , g[i][j]);
for (int i = ; i <= n; ++i)
Add(S, i, , ), Add(i + n, T, , );
while (SPFA());
while (q--) {
int C = read(), l = , r = tot, ret = ;
while (l <= r) {
int mid = (l + r) >> ;
if (val[mid] < C)
l = mid + , ret = mid;
else
r = mid - ;
}
printf("%d\n", sum[ret] + (n - ret)*C);
}
return ;
}

【BZOJ3691】游行 最小可相交路径覆盖转化的更多相关文章

  1. POJ 2594 Treasure Exploration 最小可相交路径覆盖

    最小路径覆盖 DAG的最小可相交路径覆盖: 算法:先用floyd求出原图的传递闭包,即如果a到b有路径,那么就加边a->b.然后就转化成了最小不相交路径覆盖问题. 这里解释一下floyd的作用如 ...

  2. POJ2594 Treasure Exploration[DAG的最小可相交路径覆盖]

    Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 8301   Accepted: 3 ...

  3. POJ 2594 Treasure Exploration(最小可相交路径覆盖)题解

    题意:有n个点,m条单向边,每个机器人能沿着单向边走,能重复经过一个点,问最少几个机器人走遍n个点 思路:原来以前学的都是不能相交的算法....可相交的做法是跑Floyd把能到达的都加上边,然后跑最小 ...

  4. FJUT3591 侦测到在途的聚变打击(最小不可相交路径覆盖)题解

    题意:给你n个点,点间m条路,给出在每条路要走的时间.现在有q个任务,要摧毁q个点,每次提供ci和ti表示在时间ti摧毁点ci(必须正好在时间ti才能摧毁),每个点可能需要多次摧毁(同一时间能在同一个 ...

  5. 有向无环图(DAG)的最小路径覆盖(转)

    DAG的最小路径覆盖 定义:在一个有向图中,找出最少的路径,使得这些路径经过了所有的点. 最小路径覆盖分为最小不相交路径覆盖和最小可相交路径覆盖. 最小不相交路径覆盖:每一条路径经过的顶点各不相同.如 ...

  6. 有向无环图(DAG)的最小路径覆盖

    DAG的最小路径覆盖 定义:在一个有向图中,找出最少的路径,使得这些路径经过了所有的点. 最小路径覆盖分为最小不相交路径覆盖和最小可相交路径覆盖. 最小不相交路径覆盖:每一条路径经过的顶点各不相同.如 ...

  7. HDU 3861 The King’s Problem 最小路径覆盖(强连通分量缩点+二分图最大匹配)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3861 最小路径覆盖的一篇博客:https://blog.csdn.net/qq_39627843/ar ...

  8. POJ 2594 (传递闭包 + 最小路径覆盖)

    题目链接: POJ 2594 题目大意:给你 1~N 个点, M 条有向边.问你最少需要多少个机器人,让它们走完所有节点,不同的机器人可以走过同样的一条路,图保证为 DAG. 很明显是 最小可相交路径 ...

  9. Air Raid POJ - 1422 【有向无环图(DAG)的最小路径覆盖【最小不相交路径覆盖】 模板题】

    Consider a town where all the streets are one-way and each street leads from one intersection to ano ...

随机推荐

  1. 系统调用system call以及strace/dtruss

    计算机系统的各种硬件资源是有限的,在现代多任务操作系统上同时运行的多个进程都需要访问这些资源,进程是不允许直接操作这些资源的,所有对这些资源的访问都必须有操作系统控制.也就是说操作系统是使用这些资源的 ...

  2. Exchanger实现线程间数据交换

    package com.duchong.concurrent; import java.util.ArrayList; import java.util.List; import java.util. ...

  3. linux 使用jar 打包成war

    把当前目录下的所有文件打包成game.war jar -cvfM0 game.war ./ -c   创建war包 -v   显示过程信息 -f     -M -0   这个是阿拉伯数字,只打包不压缩 ...

  4. Makefile中宏定义

    实际上是gcc命令支持-D宏定义,相当于C中的全局#define: gcc -D name gcc -D name=definition Makefile中可以定义变量(和宏很像),但是是给make解 ...

  5. Android模拟器Genymotion安装使用教程详解

    一.注册\登录 打开Genymotion官网,https://www.genymotion.com/ ,首先点击右上角的Sign in进行登录操作.如何登录就不细讲了,下面讲一下如何注册(备注:注册按 ...

  6. matlab中执行mex文件时提示GLIBCXX not found

    解决方案参考: http://stackoverflow.com/questions/8421708/glibcxx-not-found-when-compiling-vtk-example-unde ...

  7. Linux 脚本语言入门

    0.脚本编写初步介绍 (1)脚本第一行以 #!/bin/sh 开始,也可以用 #!/bin/bash 开始,但是第一行必须以这种方式开始. (2)脚本名需要以.sh结尾 (3)#开头的句子表示注释 ( ...

  8. Visual Studio Code 中实现 C++ 函数定义跳转和代码自动补全功能(25)

    方法1: 1.1 安装插件 C++ Intellisense 名称: C++ Intellisense id: austin.code-gnu-global 说明: C/C++ Intellisens ...

  9. C 语言字符串的比较

    C 语言字符串的比较 #include <stdio.h> #include <Windows.h> #include <string.h> int main(vo ...

  10. 11 模块、模块的搜索顺序、__file__内置属性、__name__属性

    模块的概念 一个python文件就是一个模块. 模块名同时也是一个标识符,需要符合标识符的命名规则. 在模块中定义的全局变量.函数.类 都是个外界提供的直接使用的工具. 模块就好比工具包,要想使用一个 ...