【2019多校第一场补题 / HDU6582】2019多校第一场E题1005Path——最短路径+网络流
题意
在一张有向图中,有一个起点和一个终点,你需要删去部分路径,使得起点到终点的最短距离增加(并不要求需要使得距离变成最大值),且删除的路径长度最短。求删去的路径总长为多少
分析
一开始理解错题意了,以为是在保证路径变成最长的路径之后,求删去的路径和最小是多少。然后就自闭了很久,还WA了好几发。后来看到题目中是 longer 而不是 longest 。突然醒悟。直接最短路径 +网络流就行,中间重新建图。
大致的过程是先跑最短路径(我用了SPFA算法,因为当数据量较大时,图为稀疏图,所以用邻接表形式),然后求出起点到每一个点的距离(保存在数组 dist 中)。然后删掉所有的边,对满足下面等式的边进行重建(网络流的边,即同时需要搭建反向的边,只不过流量为0),然后跑网络流(我用了ISAP算法,仍然是邻接表)
dist[a]−dist[b]=edge[atob]dist[a] - dist[b] = edge[a to b]dist[a]−dist[b]=edge[atob]
atoba to batob 指代这条边起点为 aaa 终点为 bbb,且满足 edge[btoa]=−edge[atob]edge[b to a] = - edge[a to b]edge[btoa]=−edge[atob]
AC代码
#include <bits/stdc++.h>
using namespace std;
#define MAXN 20100
#define MAXM 20100
bool visited[MAXN]; //标记数组
long long dist[MAXN]; //源点到顶点i的最短距离
long long path[MAXN]; //记录最短路的路径
long long enqueue_num[MAXN]; //记录入队次数
long long vertex_num; //顶点数
long long edge_num; //边数
long long source; //源点
struct Edge
{
long long to, next, cap, flow;
} edge[MAXM];
long long head[MAXN];
long long tot;
long long gap[MAXN], dep[MAXN], cur[MAXN];
void init()
{
tot = 0;
memset(head, -1, sizeof(head));
}
void addedge(long long u, long long v, long long w)
{
edge[tot].to = v;
edge[tot].cap = w;
edge[tot].next = head[u];
edge[tot].flow = 0;
head[u] = tot++;
}
bool SPFA()
{
memset(visited, 0, sizeof(visited));
memset(enqueue_num, 0, sizeof(enqueue_num));
for (long long i = 0; i < vertex_num; i++)
{
dist[i] = __LONG_LONG_MAX__;
path[i] = source;
}
queue<long long> Q;
Q.push(source);
dist[source] = 0;
visited[source] = true;
enqueue_num[source]++;
while (!Q.empty())
{
long long u = Q.front();
Q.pop();
visited[u] = 0;
for (long long curnode = head[u]; curnode != -1; curnode = edge[curnode].next)
{
if (dist[u] + edge[curnode].cap < dist[edge[curnode].to])
{
dist[edge[curnode].to] = dist[u] + edge[curnode].cap;
path[edge[curnode].to] = u;
if (!visited[edge[curnode].to])
{
Q.push(edge[curnode].to);
enqueue_num[edge[curnode].to]++;
if (enqueue_num[edge[curnode].to] >= vertex_num)
return false;
visited[edge[curnode].to] = 1;
}
}
}
}
return true;
}
long long Q[MAXN];
void BFS(long long start, long long end)
{
memset(dep, -1, sizeof(dep));
memset(gap, 0, sizeof(gap));
gap[0] = 1;
long long front = 0, rear = 0;
dep[end] = 0;
Q[rear++] = end;
while (front != rear)
{
long long u = Q[front++];
for (long long i = head[u]; i != -1; i = edge[i].next)
{
long long v = edge[i].to;
if (dep[v] != -1)
continue;
Q[rear++] = v;
dep[v] = dep[u] + 1;
gap[dep[v]]++;
}
}
}
long long S[MAXN];
long long sap(long long start, long long end, long long N)
{
BFS(start, end);
memcpy(cur, head, sizeof(head));
long long top = 0;
long long u = start;
long long ans = 0;
while (dep[start] < N)
{
if (u == end)
{
long long Min = __LONG_LONG_MAX__;
long long inser;
for (long long i = 0; i < top; i++)
{
if (Min > edge[S[i]].cap - edge[S[i]].flow)
{
Min = edge[S[i]].cap - edge[S[i]].flow;
inser = i;
}
}
for (long long i = 0; i < top; i++)
{
edge[S[i]].flow += Min;
edge[S[i] ^ 1].flow -= Min;
}
ans += Min;
top = inser;
u = edge[S[top] ^ 1].to;
continue;
}
bool flag = false;
long long v;
for (long long i = cur[u]; i != -1; i = edge[i].next)
{
v = edge[i].to;
if (edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u])
{
flag = true;
cur[u] = i;
break;
}
}
if (flag)
{
S[top++] = cur[u];
u = v;
continue;
}
long long Min = N;
for (long long i = head[u]; i != -1; i = edge[i].next)
if (edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)
{
Min = dep[edge[i].to];
cur[u] = i;
}
gap[dep[u]]--;
if (!gap[dep[u]])
return ans;
dep[u] = Min + 1;
gap[dep[u]]++;
if (u != start)
u = edge[S[--top] ^ 1].to;
}
return ans;
}
long long n, m;
int a[MAXN], b[MAXN], c[MAXN];
void reISAP()
{
init();
for (int i = 0; i < m; i++)
{
if (c[i] == dist[b[i]] - dist[a[i]])
{
addedge(a[i], b[i], c[i]);
addedge(b[i], a[i], 0);
}
}
}
int main()
{
#ifdef ACM_LOCAL
freopen("./in.txt", "r", stdin);
freopen("./out.txt", "w", stdout);
#endif
ios::sync_with_stdio(false);
long long t;
cin >> t;
while (t--)
{
cin >> n >> m;
source = 1;
vertex_num = n + 1;
init();
for (long long i = 0; i < m; i++)
{
cin >> a[i] >> b[i] >> c[i];
addedge(a[i], b[i], c[i]);
}
if (!SPFA())
{
cout << '0' << endl;
continue;
}
reISAP();
cout << sap(1, n, n) << endl;
}
return 0;
}
总结
理解了题意之后感觉就是一道板子题……
人尽皆知**题
【2019多校第一场补题 / HDU6582】2019多校第一场E题1005Path——最短路径+网络流的更多相关文章
- NOI.AC NOIP模拟赛 第一场 补记
NOI.AC NOIP模拟赛 第一场 补记 candy 题目大意: 有两个超市,每个超市有\(n(n\le10^5)\)个糖,每个糖\(W\)元.每颗糖有一个愉悦度,其中,第一家商店中的第\(i\)颗 ...
- NOI.AC NOIP模拟赛 第四场 补记
NOI.AC NOIP模拟赛 第四场 补记 子图 题目大意: 一张\(n(n\le5\times10^5)\)个点,\(m(m\le5\times10^5)\)条边的无向图.删去第\(i\)条边需要\ ...
- 2019年第一天——使用Visual Studio 2019 Preview创建第一个ASP.Net Core3.0的App
一.前言: 全文翻译自:https://www.talkingdotnet.com/creating-first-asp-net-core-3-0-app-visual-studio-2019/ Vi ...
- 计蒜客 NOIP 提高组模拟竞赛第一试 补记
计蒜客 NOIP 提高组模拟竞赛第一试 补记 A. 广场车神 题目大意: 一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n, ...
- NOI.AC NOIP模拟赛 第二场 补记
NOI.AC NOIP模拟赛 第二场 补记 palindrome 题目大意: 同[CEOI2017]Palindromic Partitions string 同[TC11326]Impossible ...
- NOI.AC NOIP模拟赛 第三场 补记
NOI.AC NOIP模拟赛 第三场 补记 列队 题目大意: 给定一个\(n\times m(n,m\le1000)\)的矩阵,每个格子上有一个数\(w_{i,j}\).保证\(w_{i,j}\)互不 ...
- 剑指offer35题:第一个只出现一次的字符+剑指offer55题:字符流中第一个不重复的字符+剑指offer51题:数组中重复的数字
在看剑指offer的时候,感觉这三个题目很像,都是用哈希表可以解决,所以把这三个题整理出来,以供复习. 剑指offer35题:第一个只出现一次的字符 题目描述:在字符串中找出第一个只出现一次的字符.如 ...
- Azure DevOps Server 2019 第一个补丁包(2019.0.1 RTW)
在Azure DevOps Server 2019正式发布后的2周左右时间,微软快速发布了第一个补丁包Azure DevOps Server 2019.0.1 RTW.Azure DevOps Ser ...
- SQL SERVER 2005中如何获取日期(一个月的最后一日、上个月第一天、最后一天、一年的第一日等等)
原文:[转]SQL SERVER 2005中如何获取日期(一个月的最后一日.上个月第一天.最后一天.一年的第一日等等) 在网上找到的一篇文章,相当不错哦O(∩_∩)O~ //C#本周第一天 ...
随机推荐
- 深入理解Tomcat(12)拾遗
前言 如何使用? 源码解读 总结 前言 Tomcat为了提高性能,在接受到socket传入的字节之后并不会马上进行编码转换,而是保持byte[]的方式,在用到的时候再进行转换.在tomcat的实现中, ...
- 《HelloGitHub》第 47 期
兴趣是最好的老师,HelloGitHub 就是帮你找到兴趣! 简介 分享 GitHub 上有趣.入门级的开源项目. 这是一个面向编程新手.热爱编程.对开源社区感兴趣 人群的月刊,月刊的内容包括:各种编 ...
- NumPy的随机函数子库——numpy.random
NumPy的随机函数子库numpy.random 导入模块:import numpy as np 1.numpy.random.rand(d0,d1,...,dn) 生成一个shape为(d0,d1, ...
- Scrum 敏捷实践中的三大角色
在我过去的近两年工作中,我们一直在应用 Scrum 敏捷项目管理方法来开展工作,今天,我先从它的角色划分来讲起,毕竟这可是它最鲜明的特征. 首先,为什么这种项目管理方法叫 Scrum ? Scrum ...
- Web中间件常见漏洞总结
一.IIS中间组件: 1.PUT漏洞 2.短文件名猜解 3.远程代码执行 4.解析漏洞 二.Apache中间组件: 1.解析漏洞 2.目录遍历 三.Nginx中间组件: 1.文件解析 2.目录遍历 3 ...
- 7-35 jmu-python-求三角形面积及周长 (10 分)
输入的三角形的三条边a.b.c,计算并输出面积和周长.假设输入三角形三边是合法整形数据. 三角形面积计算公式: ,其中s=(a+b+c)/2. import math #导入math库 math.s ...
- 原型模式故事链(3)--JS的数据类型、以及区别、区分、转化
上一章--原型链讲解:传送门:https://segmentfault.com/a/11... 在上一章讲解原型链时提到了:所有的引用类型都有一个_proto_属性,称之为隐式原型.那么引用类型是什么 ...
- HTML常用表单标签
1.表单元素 <form> HTML 表单用于收集用户输入. 代码示例: <form action="http://xxx.xxx.xxx/xxx.php" me ...
- SAP CRM Transaction处理中的权限控制
当试图打开一个Opportunity时, 系统会进行如下一系列的权限检查: 1. 检查Authorization object CRM_ORD_OP: 此处会检查当前user的partner func ...
- vue中的插槽(slot)
vue中的插槽,指的是子组件中提供给父组件使用的一个占位符,用<slot></slot>标签表示,父组件可以在这个占位符中填充任何模板代码,比如HTML.组件等,填充的内容会替 ...