(最小割)Path
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的更多相关文章
- 2019 Multi-University Training Contest 1 E Path(最短路+最小割)
题意 链接:https://vjudge.net/problem/HDU-6582 给定一个有向图,可以有重边,每条边上有一个权值表示删掉这条边的代价,问最少花费多少代价能使从s到t节点的最短路径增大 ...
- 2019HDU多校Path——最短路最小割
题目 给出一个 $n$ 个顶点 $m$ 条边的图,要求阻塞一些边,使得从 $1$ 到 $n$ 的最短路变长,求阻塞的边长度和的最小值,不必保证阻塞后可达. 分析 很显然,要阻塞的边肯定在最短路图上,先 ...
- HDU6582 Path【优先队列优化最短路 + dinic最大流 == 最小割】
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582 来源:2019 Multi-University Training Contest 1 题目大意 ...
- [2019杭电多校第一场][hdu6582]Path(最短路&&最小割)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582 题意:删掉边使得1到n的最短路改变,删掉边的代价为该边的边权.求最小代价. 比赛时一片浆糊,赛后 ...
- 2019 Multi-University Training Contest 1 Path(最短路+最小割)
题意:给你n个点 m条边 现在你能够堵住一些路 问怎样能让花费最少且让1~n走的路比最短路的长度要长 思路:先跑一边最短路 建一个最短路图 然后我们跑一边最大流求一下最小割即可 #include &l ...
- 最大流-最小割 MAXFLOW-MINCUT ISAP
简单的叙述就不必了. 对于一个图,我们要找最大流,对于基于增广路径的算法,首先必须要建立反向边. 反向边的正确性: 我努力查找了许多资料,都没有找到理论上关于反向边正确性的证明. 但事实上,我们不难理 ...
- POJ 2125 Destroying The Graph (二分图最小点权覆盖集+输出最小割方案)
题意 有一个图, 两种操作,一种是删除某点的所有出边,一种是删除某点的所有入边,各个点的不同操作分别有一个花费,现在我们想把这个图的边都删除掉,需要的最小花费是多少. 思路 很明显的二分图最小点权覆盖 ...
- ZOJ 2587 Unique Attack (最小割唯一性)
题意 判断一个无向图的割是否唯一 思路 错误思路:一开始想的是判断割边是否都是关键割边,那既然割边两端点能连通S.T点的边是关键边,那么只要遇到有某个边两端点不连通S or T则这条边就不是关键割边( ...
- POJ 3469 Dual Core CPU (最小割建模)
题意 现在有n个任务,两个机器A和B,每个任务要么在A上完成,要么在B上完成,而且知道每个任务在A和B机器上完成所需要的费用.然后再给m行,每行 a,b,w三个数字.表示如果a任务和b任务不在同一个机 ...
随机推荐
- HttpServletRequest中的request.setAttribute()和request.getSession().setAttribute()
request.setAttribute("num",value):有效范围是一个请求范围,不发送请求的界面无法获取到value的值,jsp界面获取使用EL表达式${num}:re ...
- vue复合组件----注册表单
<!doctype html> <html> <head> <meta charset="UTF-8"> <title> ...
- [Usaco2005 mar]Yogurt factory 奶酪工厂
接下来的N(1≤N10000)星期中,奶酪工厂在第i个星期要花C_i分来生产一个单位的奶酪.约克奶酪工厂拥有一个无限大的仓库,每个星期生产的多余的奶酪都会放在这里.而且每个星期存放一个单位的奶酪要花费 ...
- C++食物链【NOI2001】 并查集+建虚点
B. 食物链[NOI2001] 内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 动物王国中有三类动物A,B,C,这三类动物的食物链构成了 ...
- python基础-4 函数参数引用、lambda 匿名函数、内置函数、处理文件
上节课总结 1.三元运算 name=“name1”if 条件 else “name2” 2.深浅拷贝 数字.字符串 深浅,都一样 2.其他 浅拷贝:只拷贝第一层 深拷贝:不拷贝最后一层 3.set集合 ...
- ceph部署问题解决
注意:1.ceph-deploy实用程序将输出文件到当前目录.执行ceph-deploy时确保你在这个目录下.2.不要使用sudo调用ceph-deploy,要么以root用户身份运行它,因为它不会发 ...
- hdu-1045.fire net(缩点 + 二分匹配)
Fire Net Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Su ...
- String.indexOf()的使用方法
String.indexOf()的用途: 返回此字符串中第一个出现的指定的子字符串,如果没有找到则返回-1 源码如下: /** * Returns the index within this stri ...
- ES6判断当前页面是否微信浏览器中打开
1.使用jq判断是否用微信浏览器打开页面 var is_weixin = (function(){return navigator.userAgent.toLowerCase().indexOf('m ...
- 显式Mapping设置与常见参数介绍
原文:显式Mapping设置与常见参数介绍 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/ ...