HDU6582链接

题意

在一张有向图中,有一个起点和一个终点,你需要删去部分路径,使得起点到终点的最短距离增加(并不要求需要使得距离变成最大值),且删除的路径长度最短。求删去的路径总长为多少

分析

一开始理解错题意了,以为是在保证路径变成最长的路径之后,求删去的路径和最小是多少。然后就自闭了很久,还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——最短路径+网络流的更多相关文章

  1. NOI.AC NOIP模拟赛 第一场 补记

    NOI.AC NOIP模拟赛 第一场 补记 candy 题目大意: 有两个超市,每个超市有\(n(n\le10^5)\)个糖,每个糖\(W\)元.每颗糖有一个愉悦度,其中,第一家商店中的第\(i\)颗 ...

  2. NOI.AC NOIP模拟赛 第四场 补记

    NOI.AC NOIP模拟赛 第四场 补记 子图 题目大意: 一张\(n(n\le5\times10^5)\)个点,\(m(m\le5\times10^5)\)条边的无向图.删去第\(i\)条边需要\ ...

  3. 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 ...

  4. 计蒜客 NOIP 提高组模拟竞赛第一试 补记

    计蒜客 NOIP 提高组模拟竞赛第一试 补记 A. 广场车神 题目大意: 一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n, ...

  5. NOI.AC NOIP模拟赛 第二场 补记

    NOI.AC NOIP模拟赛 第二场 补记 palindrome 题目大意: 同[CEOI2017]Palindromic Partitions string 同[TC11326]Impossible ...

  6. NOI.AC NOIP模拟赛 第三场 补记

    NOI.AC NOIP模拟赛 第三场 补记 列队 题目大意: 给定一个\(n\times m(n,m\le1000)\)的矩阵,每个格子上有一个数\(w_{i,j}\).保证\(w_{i,j}\)互不 ...

  7. 剑指offer35题:第一个只出现一次的字符+剑指offer55题:字符流中第一个不重复的字符+剑指offer51题:数组中重复的数字

    在看剑指offer的时候,感觉这三个题目很像,都是用哈希表可以解决,所以把这三个题整理出来,以供复习. 剑指offer35题:第一个只出现一次的字符 题目描述:在字符串中找出第一个只出现一次的字符.如 ...

  8. Azure DevOps Server 2019 第一个补丁包(2019.0.1 RTW)

    在Azure DevOps Server 2019正式发布后的2周左右时间,微软快速发布了第一个补丁包Azure DevOps Server 2019.0.1 RTW.Azure DevOps Ser ...

  9. SQL SERVER 2005中如何获取日期(一个月的最后一日、上个月第一天、最后一天、一年的第一日等等)

    原文:[转]SQL SERVER 2005中如何获取日期(一个月的最后一日.上个月第一天.最后一天.一年的第一日等等) 在网上找到的一篇文章,相当不错哦O(∩_∩)O~ //C#本周第一天       ...

随机推荐

  1. MAC使用nginx分发80至8080端口

    由于项目必须要启动80端口,但是mac系统中非root用户无法直接使用1024以下的端口 2.释放apache的80端口 由于Mac OS是自带Apache服务的,它本身占用了80端口,首先你需要将A ...

  2. sql 服务器统计信息简介

    sql服务器统计是包含数据分布信息的系统对象.有时,在正则列值中.统计可以在任何支持比较操作的数据类型上创建,例如 > , < , =等. 列表2-15中,从dbo.books表中查看 I ...

  3. 做直播能有多赚钱,Python告诉你

    前面我们介绍了APP爬虫环境的搭建和mitmproxy工具的简单使用,这次我们要来一个简单的APP爬虫,尝试一下APP爬虫的简单实用,顺便让我们看看喜马拉雅上的主播到底有多赚钱. APP爬虫一般分为两 ...

  4. 何用Java8 Stream API进行数据抽取与收集

    上一篇中我们通过一个实例看到了Java8 Stream API 相较于传统的的Java 集合操作的简洁与优势,本篇我们依然借助于一个实际的例子来看看Java8 Stream API 如何抽取及收集数据 ...

  5. 用 git 钩子,检测代码规范性(eslint、standard)

    最终实现效果说明:用 git commit 提交代码之前,利用 pre-commit git 钩子,实现代码规范检测(eslint.standard 规范),符合规范之后才可以提交到 git 仓库.这 ...

  6. 「ReStory」在 Markdown 中自由书写 React 组件 (Beta)

    介绍 先睹为快 我们在开发一个小小的 React 组件库,但是我们遇到了一个大难题,那就是为我们的组件库书写一个合理的文档. 作为组件文档,我们非常希望我们的组件用例代码能够展现出来,是的我们在书写文 ...

  7. 一份简明的 Base64 原理解析

    书接上回,在 记一个 Base64 有关的 Bug 一文里,我们说到了 Base64 的编解码器有不同实现,交叉使用它们可能引发的问题等等. 这一回,我们来对 Base64 这一常用编解码技术的原理一 ...

  8. Simple: 一个支持中文和拼音搜索的 sqlite fts5插件

    之前的工作关系,需要在手机上支持中文和拼音搜索.由于手机上存储数据一般都是用 sqlite,所以是基于 sqlite3 fts5 来实现.这段时间再次入门 c++,所以想用 c++ 实现一下,一来用于 ...

  9. javascript设计模式和开发实践(阶段一)

    1,设计模式的作用:让人们写出可复用和可维护性高的程序,代价可能是,额外增加代码量: 比较形象的例子:空房间里面放东西,如果日复一日的往里面扔东西,时间久了,很难找到自己想要的东西,调整也不容易,但是 ...

  10. 利用Java实现指定文件夹下的照片以自定义格式移动

    前几天本猿的大学同学,一个漂亮的小姐姐工作时遇到了一个问题,她的需求是,在公司局域网的电脑上下载大量的图片重命名成指定得1.2.3.....以此类推,需要当天完成,我就临时给写了一个小demo. 我的 ...