[最短路,最大流最小割定理] 2019 Multi-University Training Contest 1 Path
题目:http://acm.hdu.edu.cn/showproblem.php?pid=6582
Path
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3747 Accepted Submission(s): 1075
After doing some research on the neighbourhood, Tom found that the neighbourhood consists of exactly n houses, and some of them are connected with directed road. To visit his girlfriend, Jerry needs to start from his house indexed 1 and go along the shortest path to hers, indexed n.
Now Tom wants to block some of the roads so that Jerry has to walk longer to reach his girl's home, and he found that the cost of blocking a road equals to its length. Now he wants to know the minimum total cost to make Jerry walk longer.
Note, if Jerry can't reach his girl's house in the very beginning, the answer is obviously zero. And you don't need to guarantee that there still exists a way from Jerry's house to his girl's after blocking some edges.
Each test case starts with a line containing two numbers n,m(1≤n,m≤10000), the number of houses and the number of one-way roads in the neighbourhood.
m lines follow, each of which consists of three integers x,y,c(1≤x,y≤n,1≤c≤109), denoting that there exists a one-way road from the house indexed x to y of length c.
3 4
1 2 1
2 3 1
1 3 2
1 3 3
题意:
给n个节点m条有向边,现在可以删去一些边,代价为边权,问最小代价删去一些边使得现在节点1到节点n的最短路不成立(如果1不可达n则答案为0)
思路:
可能有多条1到n的最短路,这些最短路组成图,以最小代价使图不连通就是求最小割,由最大流最小割定理可知,最小割等于最大流,所以我们先找出图中1到n的最短路新建一个图,在这个图上从1到n跑一边最大流就可求出答案
现在就是建图的问题,我们先得到1到n的最短路径dis[i],再得到n到1的最短路径dis1[i],再把原图中符合dis[u]+e[i].w+dis1[v]==dis[n](令e[i].w为节点u到v的边权)的边建一个新图,
在这个新图上从1到n跑一边dinic就可得到答案
注意:
调了一个下午,在bool operator(const node &a)const{return a.w<w;}中原来是要a.w<w才能让优先队列中w小的优先,如果是a.w>w则是w大的优先
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int amn=1e4+;
const ll inf=1e18;
struct edge{
int from,to,nex;ll w;
}eg[amn],eg1[amn],e[amn<<|];
struct node{
int p;
ll w;
node(int pp,ll ww){p=pp;w=ww;}
bool operator<(const node &a)const{return a.w<w;} ///调了一个下午,原来是要a.w<w才行,这样优先队列中才会w小的优先,如果是a.w>w则是w大的优先
};
ll head[amn],egn,head1[amn],egn1,n,m,dis[amn],dis1[amn],vis[amn],head2[amn],egn2;
void init(int n){
egn=,egn1=,egn2=; ///egn2是跑最大流的,初始为1,这样就可以从2开始加边,这样正向边和反向边相邻储存,因为2^1=3,3^1=2...所以可以异或得到正向边反向边
for(int i=;i<=n;i++)head2[i]=head1[i]=head[i]=;
}
void add(int u,int v,ll w){ ///正向图加边
eg[++egn].nex=head[u];
head[u]=egn;
eg[egn].from=u;
eg[egn].to=v;
eg[egn].w=w;
}
void add1(int u,int v,ll w){ ///反向图加边
eg1[++egn1].nex=head1[u];
head1[u]=egn1;
eg1[egn1].from=u;
eg1[egn1].to=v;
eg1[egn1].w=w;
}
void add2(int u,int v,ll w){ ///跑最大流的新图加边
e[++egn2].nex=head2[u];
head2[u]=egn2;
e[egn2].from=u;
e[egn2].to=v;
e[egn2].w=w;
} ///以1为起点跑最短路
void dijkstra(int s){
memset(vis,,sizeof vis);
for(int i=;i<=n;i++)dis[i]=inf;
dis[s]=;
priority_queue<node> q;
q.push(node(s,dis[s]));
while(q.size()){
int u=q.top().p;
ll w=q.top().w;q.pop();
if(w>dis[u])continue;
vis[u]=;
for(int i=head[u];i;i=eg[i].nex){
int v=eg[i].to;
if(!vis[v]&&((dis[v])>(eg[i].w)+(dis[u]))){
dis[v]=(eg[i].w)+dis[u];
q.push(node(v,(dis[v])));
}
}
}
}
///以n为起点跑最短路
void dijkstra1(int s){
memset(vis,,sizeof vis);
for(int i=;i<=n;i++)dis1[i]=inf;
dis1[s]=;
priority_queue<node> q;
q.push(node(s,dis1[s]));
while(q.size()){
int u=q.top().p;
ll w=q.top().w;q.pop();
if(w>dis1[u])continue;
vis[u]=;
for(int i=head1[u];i;i=eg1[i].nex){
int v=eg1[i].to;
if(!vis[v]&&((dis1[v])>(eg1[i].w)+(dis1[u]))){
dis1[v]=(eg1[i].w)+dis1[u];
q.push(node(v,(dis1[v])));
}
}
}
}
///dinic最大流
queue<int> que;
ll dist[amn],src=,sink=n;
void bfs(){
memset(dist,,sizeof dist);
while(que.size())que.pop();
vis[src]=;
que.push(src);
while(que.size()){
int u=que.front();que.pop();
for(int i=head2[u];i;i=e[i].nex){
int v=e[i].to;//cout<<'>'<<e[i].w<<' '<<v<<endl;
if(e[i].w&&!vis[v]){
que.push(v);
dist[v]=dist[u]+;
vis[v]=;
}
}
}
}
int dfs(int u,ll delta){
if(u==sink)return delta;
int ret=;
for(int i=head2[u];delta&&i;i=e[i].nex)
if(e[i].w&&(dist[e[i].to]==dist[u]+)){
ll dd=dfs(e[i].to,min(e[i].w,delta));
e[i].w-=dd;
e[i^].w+=dd;
delta-=dd;
ret+=dd;
}
return ret;
}
ll maxflow(){
ll ret=;
while(){
memset(vis,,sizeof vis);
bfs();
if(!vis[sink])return ret;//cout<<'<'<<ret<<endl;
ret+=dfs(src,inf);
}
}
int main(){
int T,x,y;ll c;
scanf("%d",&T);
while(T--){
scanf("%lld%lld",&n,&m);
init(n); ///初始化
src=,sink=n; ///设置1为源点,n为汇点
for(int i=;i<=m;i++){
scanf("%d%d%lld",&x,&y,&c);
add(x,y,c); ///正向图,为了以1为起点跑最短路
add1(y,x,c); ///反向图,为了以n为起点跑最短路
}
dijkstra(); ///以1为起点的最短路
if(dis[n]==inf){printf("0\n");continue;} ///如果1到n不可达则输出0
dijkstra1(n); ///以n为起点的最短路
for(int i=;i<=egn;i++){
// cout<<eg[i].from<<' '<<eg[i].to<<' '<<eg[i].w<<endl;
// cout<<dis[eg[i].from]<<' '<<eg[i].w<<' '<<dis1[eg[i].to]<<' '<<dis[n]<<endl<<endl;
if(dis[eg[i].from]+eg[i].w+dis1[eg[i].to]==dis[n]){ ///如果1到现在这个点u的最短路径+u到v的边权+v到n的最短路径==1到n的最短路径则u到v这条边是最短路中的一条边
add2(eg[i].from,eg[i].to,eg[i].w); ///建新图,加正向边
add2(eg[i].to,eg[i].from,); ///边权为0的反向边
}
}
printf("%lld\n",maxflow()); ///最大流等于最小割
}
}
/**
给n个节点m条有向边,现在可以删去一些边,代价为边权,问最小代价删去一些边使得现在节点1到节点n的最短路不成立(如果1不可达n则答案为0)
可能有多条1到n的最短路,这些最短路组成图,以最小代价使图不连通就是求最小割,由最大流最小割定理可知,最小割等于最大流,所以我们先找出图中1到n的最短路新建一个图,在这个图上从1到n跑一边最大流就可求出答案
现在就是建图的问题,我们先得到1到n的最短路径dis[i],再得到n到1的最短路径dis1[i],再把原图中符合dis[u]+e[i].w+dis1[v]==dis[n](令e[i].w为节点u到v的边权)的边建一个新图,
在这个新图上从1到n跑一边dinic就可得到答案
调了一个下午,在bool operator(const node &a)const{return a.w<w;}中原来是要a.w<w才能让优先队列中w小的优先,如果是a.w>w则是w大的优先
**/
[最短路,最大流最小割定理] 2019 Multi-University Training Contest 1 Path的更多相关文章
- hiho 第116周,最大流最小割定理,求最小割集S,T
小Hi:在上一周的Hiho一下中我们初步讲解了网络流的概念以及常规解法,小Ho你还记得内容么? 小Ho:我记得!网络流就是给定了一张图G=(V,E),以及源点s和汇点t.每一条边e(u,v)具有容量c ...
- hihocoder 网络流二·最大流最小割定理
网络流二·最大流最小割定理 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi:在上一周的Hiho一下中我们初步讲解了网络流的概念以及常规解法,小Ho你还记得内容么? ...
- [HihoCoder1378]网络流二·最大流最小割定理
思路: 根据最大流最小割定理可得最大流与最小割相等,所以可以先跑一遍EdmondsKarp算法.接下来要求的是经过最小割切割后的图中$S$所属的点集.本来的思路是用并查集处理所有前向边构成的残量网络, ...
- 【codevs1907】方格取数3(最大流最小割定理)
网址:http://codevs.cn/problem/1907/ 题意:在一个矩阵里选不相邻的若干个数,使这些数的和最大. 我们可以把它看成一个最小割,答案就是矩阵中的所有数-最小割.先把矩阵按国际 ...
- 牛客暑期第六场G /// 树形DP 最大流最小割定理
题目大意: 输入t,t个测试用例 每个测试用例输入n 接下来n行 输入u,v,w,树的无向边u点到v点权重为w 求任意两点间的最大流的总和 1.最大流最小割定理 即最大流等于最小割 2.无向树上的任意 ...
- 2019 Multi-University Training Contest 1 Path(最短路+最小割)
题意:给你n个点 m条边 现在你能够堵住一些路 问怎样能让花费最少且让1~n走的路比最短路的长度要长 思路:先跑一边最短路 建一个最短路图 然后我们跑一边最大流求一下最小割即可 #include &l ...
- 2019HDU多校第一场 6582 Path 【最短路+最大流最小割】
一.题目 Path 二.分析 首先肯定要求最短路,然后如何确定所有的最短路其实有多种方法. 1 根据最短路,那么最短路上的边肯定是可以满足$dist[from] + e.cost = dist[to] ...
- 【hihocoder 1378】网络流二·最大流最小割定理
[Link]:http://hihocoder.com/problemset/problem/1378 [Description] [Solution] 在求完最小割(最大流)之后; 可以在剩余网络中 ...
- 2019 Nowcoder Multi-University Training Contest 4 E Explorer
线段树分治. 把size看成时间,相当于时间 $l$ 加入这条边,时间 $r+1$ 删除这条边. 注意把左右端点的关系. #include <bits/stdc++.h> ; int X[ ...
随机推荐
- JavaScript 核心学习——继承
本篇博文讲述如何在 JavaScript 中实现继承,以及原型与原型链的知识,在附录中将会讲述 JavaScript 面向对象的常见错误. ##原型与原型链在 JavaScript 中,使用类将会付出 ...
- Flutter Widgets 之 BottomNavigationBar 和 BottomNavigationBarItem
注意:无特殊说明,Flutter版本及Dart版本如下: Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0 BottomNavigationBar 和 BottomN ...
- C++走向远洋——60(项目四、立体类族共有的抽象类)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- Nginx使用和配置
概要: Nginx 简介 Nginx 架构说明 Nginx 基础配置与使用 Nginx 反向代理与负载均衡 Nginx 实现高速缓存 Nginx 性能参数调优 一.Nginx 简介与安装 Nginx ...
- Python基本小程序
目录 Python基本小程序 一.筛选从1-100所有的奇数 二.筛选从0-100所有的偶数 三.求1-100之间所有的偶数和,奇数和 四.三个数由小到大输出 五.四个数字重复数字的三位数 Pytho ...
- python复制多层目录下的文件至其他盘符对应的目录中
一.需求 app打包需要打入一些H5进去,以便更快的加载页面.这些H5文件是散落在各个文件夹中的[如下列所示],偶尔各个文件夹还需新增文件,每次新增一个文件,需要改动jenkins上job脚本,比较麻 ...
- git上传命令步骤
1.登陆github后,进入Github首页,点击New repository新建一个项目 2. 填写相应信息后点击create repository即可 Repository name: 仓库名称( ...
- 全差分运算放大器ADA4930的分析(2)
前面解释了在ADA4930组成的单端转差分电路的输入电阻RIN的大小,可知当RF=RG=1KΩ的时候,RIN=1.33KΩ. 图1单端转差分电路 如图1所示,假设信号源为2V VPP的信号,信号源的内 ...
- 【Python3】HTML基础
[web前端]HTML基础 一.BS模式 BS(Browser-Server)模式:顾名思义为浏览器-服务器的意思,对比的话类似我们PC上面浏览器使用的产品即为BS模式产品,例如google doc. ...
- 前端每日实战:4# 视频演示如何用纯 CSS 创作一个金属光泽 3D 按钮特效
效果预览 按下右侧的"点击预览"按钮在当前页面预览,点击链接全屏预览. https://codepen.io/zhang-ou/full/MGeRRO 可交互视频教程 此视频是可以 ...