HDU6582 Path【优先队列优化最短路 + dinic最大流 == 最小割】
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582
来源:2019 Multi-University Training Contest 1
题目大意:
给定一张有向图,可以阻碍若干条有向边,花费为边的权值,求使其最短路变得更长所需的最小花费。
解题思路:
1.因为最短路可能是多条,所以找出最短路网络,然后在最短路网络中跑最小割,即最大流。就切断了原先的最短路且保证了是最小花费(最小割)。
2.值得注意的地方:边的长度限制为1e9,所以最短路数组以及一些其他的求和的值要开long long型,防止爆。
3.求最短路核心边需满足 dis[u] + edge[i].w == dis[v]。那么edge[i].w就是一条最短路的核心边。同时要确保合法性,满足dis[u] != inf && dis[v] != inf
代码如下:
#include<stdio.h>
#include<string.h>
#include<queue>
#define LL long long
#define mem(a, b) memset(a, b, sizeof(a))
const int MAXN = 1e4 + ;
const LL inf = 0x3f3f3f3f;
using namespace std; int n, m;//n个点 m条有向边
int vis[MAXN];//源点到该点的最短距离是否被确定
LL dis[MAXN]; struct Edge
{
int to, next;
LL w;
}e[MAXN];
int head[MAXN], cnt; void add(int a, int b, int c)
{
e[++ cnt].to = b;
e[cnt].w = c;
e[cnt].next = head[a];
head[a] = cnt;
} struct Node
{
int pot;
LL dis; //点 以及 源点到该点的最短距离
bool operator < (const Node &a)const//重载 按照dis从小到大排序
{
return dis > a.dis;
}
}no; priority_queue<Node> Q;
void dij() //优先队列优化的最短路
{
mem(vis, ), mem(dis, inf);
no.dis = , no.pot = ;
dis[] = ;
Q.push(no);
while(!Q.empty())
{
Node a = Q.top();//优先队列无front操作
Q.pop();
if(vis[a.pot])
continue;
vis[a.pot] = ;
for(int i = head[a.pot]; i != -; i = e[i].next)//松弛操作
{
int to = e[i].to;
if(!vis[to] && dis[a.pot] + e[i].w < dis[to])
{
dis[to] = dis[a.pot] + e[i].w;
no.pot = to, no.dis = dis[to];
Q.push(no);
}
}
}
// printf("%d\n", dis[n]);
} struct edge_
{
int to, next, flow;
}e_[ * MAXN];//要加反向边 开2倍
int head_[MAXN]; void add_(int a, int b, int c)
{
e_[++ cnt].to = b;
e_[cnt].flow = c;
e_[cnt].next = head_[a];
head_[a] = cnt;
} int dep[MAXN];
int bfs(int st, int ed)
{
if(st == ed)
return ;
mem(dep, -);
queue<int >Q_;
dep[st] = ;
Q_.push(st);
while(!Q_.empty())
{
int now = Q_.front();
Q_.pop();
for(int i = head_[now]; i != -; i = e_[i].next)
{
int to = e_[i].to;
if(e_[i].flow > && dep[to] == -)
{
dep[to] = dep[now] + ;
Q_.push(to);
}
}
}
return dep[ed] != -;
} int dfs(int now, int ed, int inc)
{
if(now == ed)
return inc;
for(int i = head_[now]; i != -; i = e_[i].next)
{
int to = e_[i].to;
if(e_[i].flow > && dep[to] == dep[now] + )
{
int min_flow = dfs(to, ed, min(inc, e_[i].flow));
if(min_flow > )
{
e_[i].flow -= min_flow;
e_[i ^ ].flow += min_flow;
return min_flow;
}
}
}
return -;
} LL dinic(int st, int ed)
{
LL ans = ;
while(bfs(st, ed))
{
while()
{
int inc = dfs(st, ed, inf);
if(inc == -)
break;
ans += inc;
}
}
return ans;
} int main()
{
int T;
scanf("%d", &T);
while(T --)
{
scanf("%d%d", &n, &m);
cnt = , mem(head, -); //最短路的边从1开始存 head初始化为-1
for(int i = ; i <= m; i ++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c); //有向边 加一条即可
}
dij(); //跑最短路
if(dis[n] == inf) //特判
{
printf("0\n");
continue;
}
cnt = -, mem(head_, -);//从0开始存 才能进行 ^ 运算
for(int i = ; i <= n; i ++)
{
for(int j = head[i]; j != -; j = e[j].next)
{
int to = e[j].to;
if(dis[i] + e[j].w == dis[to] && dis[to] != inf && dis[i] != inf) //得到最短路核心边(因为可能是多条)
{
add_(i, to, e[j].w);
add_(to, i, ); //反向边容量为 0
}
}
}
printf("%lld\n", dinic(, n));
}
return ;
}
优先队列优化dij+最大流dinic
HDU6582 Path【优先队列优化最短路 + dinic最大流 == 最小割】的更多相关文章
- 2020牛客暑期多校训练营 第二场 I Interval 最大流 最小割 平面图对偶图转最短路
LINK:Interval 赛时连题目都没看. 观察n的范围不大不小 而且建图明显 考虑跑最大流最小割. 图有点稠密dinic不太行. 一个常见的trick就是对偶图转最短路. 建图有点复杂 不过建完 ...
- hdu 2435 dinic算法模板+最小割性质
#include<stdio.h> #include<queue> #include<string.h> using namespace std; #define ...
- 晴天小猪历险记之Hill(Dijkstra优先队列优化)
描述 这一天,他来到了一座深山的山脚下,因为只有这座深山中的一位隐者才知道这种药草的所在.但是上山的路错综复杂,由于小小猪的病情,晴天小猪想找一条需时最少的路到达山顶,但现在它一头雾水,所以向你求助. ...
- 2019HDU多校Path——最短路最小割
题目 给出一个 $n$ 个顶点 $m$ 条边的图,要求阻塞一些边,使得从 $1$ 到 $n$ 的最短路变长,求阻塞的边长度和的最小值,不必保证阻塞后可达. 分析 很显然,要阻塞的边肯定在最短路图上,先 ...
- Luogu2046 NOI2010 海拔 平面图、最小割、最短路
传送门 首先一个不知道怎么证的结论:任意点的\(H\)只会是\(0\)或\(1\) 那么可以发现原题的本质就是一个最小割,左上角为\(S\),右下角为\(T\),被割开的两个部分就是\(H=0\)与\ ...
- cf786E ALT (最小割+倍增优化建图)
如果把“我全都要”看作是我全不要的话,就可以用最小割解决啦 源点S,汇点T 我们试图让每个市民作为一个等待被割断的路径 把狗狗给市民:建边(S,i,1),其中i是市民 把狗狗给守卫:建边(j,T,1) ...
- 最短路算法模板合集(Dijkstar,Dijkstar(优先队列优化), 多源最短路Floyd)
再开始前我们先普及一下简单的图论知识 图的保存: 1.邻接矩阵. G[maxn][maxn]; 2.邻接表 邻接表我们有两种方式 (1)vector< Node > G[maxn]; 这个 ...
- POJ 1511 Invitation Cards(单源最短路,优先队列优化的Dijkstra)
Invitation Cards Time Limit: 8000MS Memory Limit: 262144K Total Submissions: 16178 Accepted: 526 ...
- hdu 1874(最短路 Dilkstra +优先队列优化+spfa)
畅通工程续 Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
随机推荐
- 005_linux驱动之_class_device_create函数
(一)解析class_device_create函数 (二)当我们使用class_create创建一个类之后我们就可以使用class_device_create函数在这个类下面创建一个设备了,cl ...
- Oracle 后台进程(一)简介
一.什么是Oracle数据库后台进程 为了时系统性能最好并能够协调多个用户,多进程系统使用了一些附加进程,成为后台进程. 在许多操作系统中,后台进程是在实例启动时自动建立的.一个Oracle实例可以包 ...
- 五十六. playbook基础 、 playbook进阶
1.playbook练习 安装Apache并修改监听端口为8080 修改ServerName配置,执行apachectl -t命令不报错 设置默认主页hello world 启动服务并设开机自启 ...
- web批量下载文件到本地
JavaWeb 文件下载功能 文件下载的实质就是文件拷贝,将文件从服务器端拷贝到浏览器端,所以文件下载需要IO技术将服务器端的文件读取到,然后写到response缓冲区中,然后再下载到个人客户端. 1 ...
- python 版本及pip安装相关
python2与python3 由于历史原因,Python有两个大的版本分支,Python2和Python3,又由于一些库只支持某个版本分支,所以需要在电脑上同时安装Python2和Python3,因 ...
- 把字符串当做js代码执行的方法
字符串还能当做javascript代码来执行?你能想到哪些方法? 1.setInterval("要执行的字符串",500);window对象的方法既可以传字符串,也可以传函数.该函 ...
- git reset 版本回退操作
1 git回退命令 git reset --hard GIT_HEAD GIT_HEAD是你具体要回退的分支: 如图: 注: 查询GIT_HEAD可以通过两个命令:git log 获取未删除 ...
- 【分享】《美国数学本科生,研究生基础课程参考书目(个人整理)》[DJVU][VERYCD]
目录: 第一学年 几何与拓扑: 1.James R. Munkres, Topology:较新的拓扑学的教材适用于本科高年级或研究生一年级: 2.Basic Topology by Armstrong ...
- php判断变量类型
php判断变量类型 一.总结 一句话总结: gettype()函数:gettype(1);返回的是integer is_array():is系列函数 1.PHP empty.isset.isnull的 ...
- 以太坊 Geth 环境搭建(Ubuntu)
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u014409380/article/details/79897335 时隔多日,我又想起来更新博客, ...