[最短路,最大流最小割定理] 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[ ...
随机推荐
- 每日一译系列-模块化css怎么玩(译文)
原文链接:How Css Modules Work 原文作者是Preact的作者 这是一篇关于如何使用Css Modules的快速介绍,使用到的工具是Webpack吊炸的css-loader 首先,我 ...
- Flutter Widgets 之 SnackBar
注意:无特殊说明,Flutter版本及Dart版本如下: Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0 基础用法 应用程序有时候需要弹出消息提示用户,比如'网络连 ...
- 10分钟进阶SpringBoot - 05. 数据访问之JDBC(附加源码分析+代码下载)
10分钟进阶SpringBoot - 05. 数据访问之JDBC 代码下载:https://github.com/Jackson0714/study-spring-boot.git 一.JDBC是什么 ...
- 可视化工作流程设计开发OA系统,一两个程序员就搞定!
随着信息化的发展,越来越多的公司老板要求实现企业审批流程化.一个公司在初期,人员少,流程简单,员工也会经常不按工作流程来走,甚至有些跨部门的工作因为关系原因,没有走工作流程就实施,导致后期出现问题或者 ...
- 不要忽视Managed code stripping的副作用
0x00 前言 Unity 2018.3之后,新的“Managed Stripping Level”选项将替换 player settings 中原有的“Stripping Level”选项. 这个新 ...
- 【jQuery学习日记】jQuery实现滚动动画
需要实现的效果 样式分析: 2个主要部分,头部的标题和导航部分,和主要的功能实现区域: 1.头部 <div id="header"> <h1>动漫视频< ...
- 高性能MySQL之锁详解
一.背景 MySQL里面的锁大致可以分成全局锁.表级锁和行锁三类.数据库锁的设计的初衷是处理并发问题.我们知道多用户共享资源的时候,就有可能会出现并发访问的时候,数据库就需要合理的控制资源的访问规则, ...
- .Net 特性分析与妙用
一.特性是什么 1.想象很多小伙伴们都看过在一个类上方.或者在控制器见过类似的东东,加上之后就可以标识这个类或者方法就具备了某些特点 ,那我们就进入它的内心一探究竟吧. 2.我们进入某个特性之后,可以 ...
- python小白入门
阅读目录 一python介绍 二安装python解释器 三第一个python程序 四变量 五用户与程序交互 六基本数据类型 七格式化输出 八基本运算符 九流程控制之if...else 十流程控制之wh ...
- 【Python challenge】通关代码及攻略(0-11)
前言: 最近找到一个有关python的游戏闯关,这是游戏中的思考及通关攻略 最开始位于:http://www.pythonchallenge.com/pc/def/0.html 第0关 题目分析 提示 ...