[最短路,最大流最小割定理] 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

Problem Description

Years later, Jerry fell in love with a girl, and he often walks for a long time to pay visits to her. But, because he spends too much time with his girlfriend, Tom feels neglected and wants to prevent him from visiting her.
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.

Input

The input begins with a line containing one integer T(1≤T≤10), the number of test cases.
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.

Output

Print T lines, each line containing a integer, the answer.

Sample Input

1
3 4
1 2 1
2 3 1
1 3 2
1 3 3

Sample Output

3

Source

2019 Multi-University Training Contest 1

Recommend

We have carefully selected several similar problems for you:  6718 6717 6716 6715 6714

题意:

给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大的优先

  1 #include<bits/stdc++.h>
  2 typedef long long ll;
  3 using namespace std;
  4 const int amn=1e4+5;
  5 const ll inf=1e18;
  6 struct edge{
  7     int from,to,nex;ll w;
  8 }eg[amn],eg1[amn],e[amn<<2|1];
  9 struct node{
 10     int p;
 11     ll w;
 12     node(int pp,ll ww){p=pp;w=ww;}
 13     bool operator<(const node &a)const{return a.w<w;}   ///调了一个下午,原来是要a.w<w才行,这样优先队列中才会w小的优先,如果是a.w>w则是w大的优先
 14 };
 15 ll head[amn],egn,head1[amn],egn1,n,m,dis[amn],dis1[amn],vis[amn],head2[amn],egn2;
 16 void init(int n){
 17     egn=0,egn1=0,egn2=1;    ///egn2是跑最大流的,初始为1,这样就可以从2开始加边,这样正向边和反向边相邻储存,因为2^1=3,3^1=2...所以可以异或得到正向边反向边
 18     for(int i=1;i<=n;i++)head2[i]=head1[i]=head[i]=0;
 19 }
 20 void add(int u,int v,ll w){     ///正向图加边
 21     eg[++egn].nex=head[u];
 22     head[u]=egn;
 23     eg[egn].from=u;
 24     eg[egn].to=v;
 25     eg[egn].w=w;
 26 }
 27 void add1(int u,int v,ll w){    ///反向图加边
 28         eg1[++egn1].nex=head1[u];
 29         head1[u]=egn1;
 30         eg1[egn1].from=u;
 31         eg1[egn1].to=v;
 32         eg1[egn1].w=w;
 33     }
 34 void add2(int u,int v,ll w){    ///跑最大流的新图加边
 35         e[++egn2].nex=head2[u];
 36         head2[u]=egn2;
 37         e[egn2].from=u;
 38         e[egn2].to=v;
 39         e[egn2].w=w;
 40     }
 41
 42 ///以1为起点跑最短路
 43 void dijkstra(int s){
 44     memset(vis,0,sizeof vis);
 45     for(int i=0;i<=n;i++)dis[i]=inf;
 46     dis[s]=0;
 47     priority_queue<node> q;
 48     q.push(node(s,dis[s]));
 49     while(q.size()){
 50         int u=q.top().p;
 51         ll w=q.top().w;q.pop();
 52         if(w>dis[u])continue;
 53         vis[u]=1;
 54         for(int i=head[u];i;i=eg[i].nex){
 55             int v=eg[i].to;
 56             if(!vis[v]&&((dis[v])>(eg[i].w)+(dis[u]))){
 57                 dis[v]=(eg[i].w)+dis[u];
 58                 q.push(node(v,(dis[v])));
 59             }
 60         }
 61     }
 62 }
 63 ///以n为起点跑最短路
 64 void dijkstra1(int s){
 65     memset(vis,0,sizeof vis);
 66     for(int i=0;i<=n;i++)dis1[i]=inf;
 67     dis1[s]=0;
 68     priority_queue<node> q;
 69     q.push(node(s,dis1[s]));
 70     while(q.size()){
 71         int u=q.top().p;
 72         ll w=q.top().w;q.pop();
 73         if(w>dis1[u])continue;
 74         vis[u]=1;
 75         for(int i=head1[u];i;i=eg1[i].nex){
 76             int v=eg1[i].to;
 77             if(!vis[v]&&((dis1[v])>(eg1[i].w)+(dis1[u]))){
 78                 dis1[v]=(eg1[i].w)+dis1[u];
 79                 q.push(node(v,(dis1[v])));
 80             }
 81         }
 82     }
 83 }
 84 ///dinic最大流
 85 queue<int> que;
 86 ll dist[amn],src=1,sink=n;
 87 void bfs(){
 88     memset(dist,0,sizeof dist);
 89     while(que.size())que.pop();
 90     vis[src]=1;
 91     que.push(src);
 92     while(que.size()){
 93         int u=que.front();que.pop();
 94         for(int i=head2[u];i;i=e[i].nex){
 95             int v=e[i].to;//cout<<‘>‘<<e[i].w<<‘ ‘<<v<<endl;
 96             if(e[i].w&&!vis[v]){
 97                 que.push(v);
 98                 dist[v]=dist[u]+1;
 99                 vis[v]=1;
100             }
101         }
102     }
103 }
104 int dfs(int u,ll delta){
105     if(u==sink)return delta;
106     int ret=0;
107     for(int i=head2[u];delta&&i;i=e[i].nex)
108     if(e[i].w&&(dist[e[i].to]==dist[u]+1)){
109         ll dd=dfs(e[i].to,min(e[i].w,delta));
110         e[i].w-=dd;
111         e[i^1].w+=dd;
112         delta-=dd;
113         ret+=dd;
114     }
115     return ret;
116 }
117 ll maxflow(){
118     ll ret=0;
119     while(1){
120         memset(vis,0,sizeof vis);
121         bfs();
122         if(!vis[sink])return ret;//cout<<‘<‘<<ret<<endl;
123         ret+=dfs(src,inf);
124     }
125 }
126 int main(){
127     int T,x,y;ll c;
128     scanf("%d",&T);
129     while(T--){
130         scanf("%lld%lld",&n,&m);
131         init(n);            ///初始化
132         src=1,sink=n;       ///设置1为源点,n为汇点
133         for(int i=1;i<=m;i++){
134             scanf("%d%d%lld",&x,&y,&c);
135             add(x,y,c);     ///正向图,为了以1为起点跑最短路
136             add1(y,x,c);    ///反向图,为了以n为起点跑最短路
137         }
138         dijkstra(1);        ///以1为起点的最短路
139         if(dis[n]==inf){printf("0\n");continue;}    ///如果1到n不可达则输出0
140         dijkstra1(n);       ///以n为起点的最短路
141         for(int i=1;i<=egn;i++){
142 //            cout<<eg[i].from<<‘ ‘<<eg[i].to<<‘ ‘<<eg[i].w<<endl;
143 //            cout<<dis[eg[i].from]<<‘ ‘<<eg[i].w<<‘ ‘<<dis1[eg[i].to]<<‘ ‘<<dis[n]<<endl<<endl;
144             if(dis[eg[i].from]+eg[i].w+dis1[eg[i].to]==dis[n]){     ///如果1到现在这个点u的最短路径+u到v的边权+v到n的最短路径==1到n的最短路径则u到v这条边是最短路中的一条边
145                 add2(eg[i].from,eg[i].to,eg[i].w);  ///建新图,加正向边
146                 add2(eg[i].to,eg[i].from,0);        ///边权为0的反向边
147             }
148         }
149         printf("%lld\n",maxflow());     ///最大流等于最小割
150     }
151 }
152 /**
153 给n个节点m条有向边,现在可以删去一些边,代价为边权,问最小代价删去一些边使得现在节点1到节点n的最短路不成立(如果1不可达n则答案为0)
154 可能有多条1到n的最短路,这些最短路组成图,以最小代价使图不连通就是求最小割,由最大流最小割定理可知,最小割等于最大流,所以我们先找出图中1到n的最短路新建一个图,在这个图上从1到n跑一边最大流就可求出答案
155 现在就是建图的问题,我们先得到1到n的最短路径dis[i],再得到n到1的最短路径dis1[i],再把原图中符合dis[u]+e[i].w+dis1[v]==dis[n](令e[i].w为节点u到v的边权)的边建一个新图,
156 在这个新图上从1到n跑一边dinic就可得到答案
157 调了一个下午,在bool operator(const node &a)const{return a.w<w;}中原来是要a.w<w才能让优先队列中w小的优先,如果是a.w>w则是w大的优先
158 **/

原文地址:https://www.cnblogs.com/Railgun000/p/11408406.html

时间: 2024-07-28 17:54:34

[最短路,最大流最小割定理] 2019 Multi-University Training Contest 1 Path的相关文章

hihocoder 网络流二&#183;最大流最小割定理

网络流二·最大流最小割定理 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi:在上一周的Hiho一下中我们初步讲解了网络流的概念以及常规解法,小Ho你还记得内容么? 小Ho:我记得!网络流就是给定了一张图G=(V,E),以及源点s和汇点t.每一条边e(u,v)具有容量c(u,v).网络流的最大流问题求解的就是从s到t最多能有多少流量. 小Hi:那这个问题解决办法呢? 小Ho:解决网络流的基本思路就是寻找增广路,不断更新残留网络.直到找不到新的增广路,此时得到的

网络的最大流最小割定理

什么是流(flow): 在一个有向图中,只有出去的边没有进来的边的节点叫做源(source),只有进来的边没有出去的边的节点叫做汇(sink),其它的节点进来的边和出去的边应该是平衡的. 边上可以加权值,假设对于一个交通图来说,可以认为边上的权重为一条道路上的最大流量.那么对于图中任意两个节点来说,它们之间可以存在很多路径,每条路径上可以负载的最大流量应该是这条路径上权重最小的那条边所能承载的流量(联想一下“瓶颈”这个词,或者木桶理论),那么所有的路径上所负载流量之和也就是这两个节点之间多能通过

【codevs1907】方格取数3(最大流最小割定理)

网址:http://codevs.cn/problem/1907/ 题意:在一个矩阵里选不相邻的若干个数,使这些数的和最大. 我们可以把它看成一个最小割,答案就是矩阵中的所有数-最小割.先把矩阵按国际象棋棋盘黑白染色(即把相邻的点分别染成白色和黑色),然后黑点连源点,白点连汇点.割掉一个点到源/汇的边就是不选择这个点,最后的目的就是使源到汇不连通(不引发题目不能选择位置相邻的数的矛盾). 然而最小割怎么求呢? 于是我们就要引入一个定理:最大流最小割定理.它的意思就是说,在一个图中,a点到b点的最

网络流基础-最大流最小割定理

最大流最小割定理,指网络流的最大流等于其最小割. 最大流指符合三个性质的前提下,从S到T能流过的最大流量. 最小割指符合割的定义,最小的割容量. 求最大流: 不断寻找增广路,计算能增加的最小流量,然后增加. 找到一条增光路,最多能流过2,则: 找到第二条路径: 最后还剩a-c-e一条,则可计算出最大流量为4. 但遇到以下情况,且第一条路径为a-b-c-d时,就不行了: 此时需要增加反向路径,即当减去增广路时,反向加上减去的流量,提供后悔的选择: 这样,当考虑a-c-b-d时,可以对冲掉b-c的流

网络流(三)最大流最小割定理

转载:https://blog.csdn.net/w417950004/article/details/50538948 割(CUT)是网络中顶点的划分,它把网络中的所有顶点划分成两个顶点的集合源点S和汇点T.记为CUT(S,T). 如下图:源点:s=1;汇点:t=5.框外是容量,框内是流量 如下图是一个图的割.顶点集合S={1,2,3}和T={4,5}构成一个割. 如果一条弧的两个顶点分别属于顶点集S和T那么这条弧称为割CUT(S,T)的一条割边.  从S指向T的割边是正向割边,从T指向S的割

【NOIP模拟赛(六)】花园的守护之神(greendam)-最短路-最大流最小割

Problem Greemdam 题目大意 给一个图$G=(V,E)$,求要使这个图的最短路增长所需要增加的最小权值的值. Solution 既然是要求这个玩意儿,我们可以排除除了最短路以外的所有路径,因为这些是无用的. 对于每一条最短路路径,如果这条路径与任意一个最短路路径有相同的一条边, 那我们只需要在这条边权值加一就可以保证这两个最短路都增加了. 所以我们转化为求不相交边的最短路路径数, 其实就是这个图的最小割. 我们给最短路的图每个边附权值为1(因为前权值是无用的), 跑一遍最大流即可.

最大流最小割定理

一.割的定义 例子: 2.割边的概念 例子: 3.割的容量 二.网络流与割的关系 1.结论 2.定理1: 3.推论: 4.定理2 5.定理3: 6.结论: 7.一些1求解: 三.应用实例 最大净收益: 三个实验,三个实验器材:进行实验2与实验3的净收益: 至此,最大流与最小割的理论介绍已经结束,感谢有这样一份ppt,基本上能明白其中的原理:这个理论在图割算法中有应用,接下来会继续探究一下.

网络流(二)——最大流最小割定理

最小割<1>什么是割?    引例:你的仇人是一个工厂老板.你要炸掉一些车,让他每个货物都运不到销售点.        炸掉越大的车,你越容易被发现.你希望炸掉的车的容量之和尽量小.        最小化这个值.    定义:选出一些边的集合,使得删除它们之后从源点无法到达汇点,那么这个集合就叫做一个割.        这些边的容量之和称作这个割的容量.<2>最小割最大流定理    定理1:任取一个割,其容量大于最大流的流量.        证明: 从源点到汇点的每条路径都会经过割

2019HDU多校第一场 6582 Path 【最短路+最大流最小割】

一.题目 Path 二.分析 首先肯定要求最短路,然后如何确定所有的最短路其实有多种方法. 1 根据最短路,那么最短路上的边肯定是可以满足$dist[from] + e.cost = dist[to]$.所以可以求一遍后根据这个公式再向网络图中的加边即可. 2 可以从源点和汇点分别求最短路,然后根据每条边肯定满足$dist1[e.from] + e.cost + dist2[e.to] = dij$,再加边就行了. 确定最短路后,由于是求最小割,直接跑$Dinic$求出最大流就可以了. 三.AC