http://acm.hdu.edu.cn/showproblem.php?pid=6582

思路:找到最短路核心边建图,跑一遍最小割,最短路核心边的定义为设起点到每个点的最短距离为d[i],每个点到终点的最短路为d2[i],如果一条边起点为u,终点为v,边权为w,若d[u]+d2[v]+w==d[n]则这是一条最短路核心边。所以先用spfa求d[i],然后反向spfa求d2[i],最后建图dinic求出答案。

#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cstdio>
#include<stack>
#include<cmath>
#include<iostream>
#define ll long long
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=;
const int maxm=;
const ll inf=1e18;
struct node{
int u,v,nxt;
ll w;
}e[*maxm],e2[*maxm],e3[*maxm];
int h[maxn],h2[maxn],h3[maxn],depth[maxn];
ll d[maxn],d2[maxn];
bool vis[maxn];
int n,m,st,ed,cnt,cnt2,cnt3;
void init()
{
memset(h,-,sizeof(h));
memset(h2,-,sizeof(h2));
memset(h3,-,sizeof(h3));
for(int i=;i<=n;i++)
d[i]=d2[i]=inf;
cnt=cnt2=cnt3=;
} void add(int u,int v,ll w)//正向建边
{
e[cnt].u=u,e[cnt].v=v,e[cnt].w=w;
e[cnt].nxt=h[u];h[u]=cnt++;
} void add2(int u,int v,ll w)//反向建边
{
e2[cnt2].u=u,e2[cnt2].v=v,e2[cnt2].w=w;
e2[cnt2].nxt=h2[u],h2[u]=cnt2++;
}
void add3(int u,int v,ll w)//重新建边
{
e3[cnt3].u=u,e3[cnt3].v=v,e3[cnt3].w=w;
e3[cnt3].nxt=h3[u],h3[u]=cnt3++;
} bool spfa()//求每点到1的最短距离
{
queue<int> q;
memset(vis,,sizeof(vis));
d[st]=;
vis[st]=;
q.push(st);
while(!q.empty())
{
int u=q.front();q.pop();
vis[u]=;
for(int i=h[u];i!=-;i=e[i].nxt)
{
int v=e[i].v;
ll w=e[i].w;
if(d[v]>d[u]+w)
{
d[v]=d[u]+w;
if(!vis[v])
{
vis[v]=;
q.push(v);
}
}
}
}
return d[n]==inf;
} void re_spfa()//求每点到n的最短距离
{
queue<int> q;
memset(vis,,sizeof(vis));
d2[ed]=;
vis[ed]=;
q.push(ed);
while(!q.empty())
{
int u=q.front();q.pop();
vis[u]=;
for(int i=h2[u];i!=-;i=e2[i].nxt)
{
int v=e2[i].v;
ll w=e2[i].w;
if(d2[v]>d2[u]+w)
{
d2[v]=d2[u]+w;
if(!vis[v])
{
vis[v]=;
q.push(v);
}
}
}
}
} void create_map()//重新建边
{
for(int i=;i<cnt;i++)
{
int u=e[i].u;
int v=e[i].v;
ll w=e[i].w;
if((d[u]+d2[v]+w==d[ed])&&(d[u]<inf&&d2[v]<inf))
{//最短路核心边
add3(u,v,w);
add3(v,u,);
}
}
} bool bfs(){//dinic分层
queue<int> que;
memset(depth,,sizeof(depth));
que.push(st);
depth[st]=;
while(!que.empty()){
int u=que.front();
que.pop();
if(u==ed)
return true;
for(int i=h3[u];i!=-;i=e3[i].nxt){
int v=e3[i].v;
ll w=e3[i].w;
if(!depth[v]&&w){
depth[v]=depth[u]+;
que.push(v);
}
}
}
return false;
} ll dfs(int u,ll dis)
{
if(u==ed)
return dis;
ll res=;
for(int i=h3[u];i!=-;i=e3[i].nxt)
{
int v=e3[i].v;
ll w=e3[i].w;
if((depth[v]==depth[u]+)&&w)
{
ll di=dfs(v,min(w,dis-res));
e3[i].w-=di;
e3[i^].w+=di;
res+=di;
if(res==dis)
return dis;
}
}
return res;
} void dinic()//dinic求最小割
{
ll ans=;
while(bfs())
{
ans+=dfs(st,inf);
}
printf("%lld\n",ans);
} int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
st=,ed=n;
init();
for(int i=;i<m;i++)
{
int u,v;ll w;
scanf("%d%d%lld",&u,&v,&w);
add(u,v,w);
add2(v,u,w);
}
if(spfa())//特判,没有最短路
printf("0\n");
else
{
re_spfa();
create_map();
dinic();
}
}
return ;
}

(最小割)Path的更多相关文章

  1. 2019 Multi-University Training Contest 1 E Path(最短路+最小割)

    题意 链接:https://vjudge.net/problem/HDU-6582 给定一个有向图,可以有重边,每条边上有一个权值表示删掉这条边的代价,问最少花费多少代价能使从s到t节点的最短路径增大 ...

  2. 2019HDU多校Path——最短路最小割

    题目 给出一个 $n$ 个顶点 $m$ 条边的图,要求阻塞一些边,使得从 $1$ 到 $n$ 的最短路变长,求阻塞的边长度和的最小值,不必保证阻塞后可达. 分析 很显然,要阻塞的边肯定在最短路图上,先 ...

  3. HDU6582 Path【优先队列优化最短路 + dinic最大流 == 最小割】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582 来源:2019 Multi-University Training Contest 1 题目大意 ...

  4. [2019杭电多校第一场][hdu6582]Path(最短路&&最小割)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582 题意:删掉边使得1到n的最短路改变,删掉边的代价为该边的边权.求最小代价. 比赛时一片浆糊,赛后 ...

  5. 2019 Multi-University Training Contest 1 Path(最短路+最小割)

    题意:给你n个点 m条边 现在你能够堵住一些路 问怎样能让花费最少且让1~n走的路比最短路的长度要长 思路:先跑一边最短路 建一个最短路图 然后我们跑一边最大流求一下最小割即可 #include &l ...

  6. 最大流-最小割 MAXFLOW-MINCUT ISAP

    简单的叙述就不必了. 对于一个图,我们要找最大流,对于基于增广路径的算法,首先必须要建立反向边. 反向边的正确性: 我努力查找了许多资料,都没有找到理论上关于反向边正确性的证明. 但事实上,我们不难理 ...

  7. POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)

    题意 有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少. 思路 很明显的二分图最小点权覆盖 ...

  8. ZOJ 2587 Unique Attack (最小割唯一性)

    题意 判断一个无向图的割是否唯一 思路 错误思路:一开始想的是判断割边是否都是关键割边,那既然割边两端点能连通S.T点的边是关键边,那么只要遇到有某个边两端点不连通S or T则这条边就不是关键割边( ...

  9. POJ 3469 Dual Core CPU (最小割建模)

    题意 现在有n个任务,两个机器A和B,每个任务要么在A上完成,要么在B上完成,而且知道每个任务在A和B机器上完成所需要的费用.然后再给m行,每行 a,b,w三个数字.表示如果a任务和b任务不在同一个机 ...

随机推荐

  1. Series.str方法

    1 对dataframe的某一列用str处理后,其类型是<class 'pandas.core.strings.StringMethods'>.可以对df.['列名'].str直接进行切片 ...

  2. python基础数据类型补充以及编码的进阶

    一.基本数据类型的补充循环列表改变列表大小的问题#请把列表中索引为基数的元素写出l1=[1,2,3,4,5,6]for i in l1: if i%2!=0: print(i)结果:135二:基本数据 ...

  3. IDEA怎样在3.0中修改彩色字体。

    首先 找到 第一个File之后再找到Setting点击打开之后有Editor里面有colors和Fonts在下面是language  defaults        Semantic highligh ...

  4. Hyperledger:Fabric CA 用户指南 [译]

    Fabric CA 用户指南 Fabric CA 是 Hyperledger Fabric 的官方配套认证设施. 原文链接:http://hyperledger-fabric.readthedocs. ...

  5. oracle--单表查询

    ---单表的查询学习 --查询表的所有数据 select * from 表名;*代表所有 select * from emp; --查询表中指定字段的值 select 字段名1,字段名2,...fro ...

  6. Codeforces 916E(思维+dfs序+线段树+LCA)

    题面 传送门 题目大意:给定初始根节点为1的树,有3种操作 1.把根节点更换为r 2.将包含u,v的节点的最小子树(即lca(u,v)的子树)所有节点的值+x 3.查询v及其子树的值之和 分析 看到批 ...

  7. BitMap的原理和实现

    相关概念 基础类型 在java中: byte -> 8 bits -->1字节 char -> 16 bit -->2字节 short -> 16 bits --> ...

  8. bzoj3156 防御准备(斜率优化)

    Time Limit: 10 Sec  Memory Limit: 512 MB Input 第一行为一个整数N表示战线的总长度. 第二行N个整数,第i个整数表示在位置i放置守卫塔的花费Ai. Out ...

  9. 搜索(BFS)---计算在网格中从原点到特定点的最短路径长度

    计算在网格中从原点到特定点的最短路径长度 [[1,1,0,1], [1,0,1,0], [1,1,1,1], [1,0,1,1]] 题目描述: 1表示可以经过某个地方,求解从(0,0)位置到(tr,t ...

  10. Connection keepalive

    TCP    keepalive = 心跳包 linux  tcp keepalive 参数: tcp_keepalive_time:       7200 tcp_keepalive_intvl  ...