传送门

•题意

有n个城市,标号1-n

现花费最小的代价堵路

使得从1号城市到n号城市的路径边长

(注意只是变长不是最长)

堵一条路的代价是这条路的权值

•思路

在堵路以前,从1到n的最小路径当然是最短路

想要路径边长就要在最短路上动手脚

把从1到n的最短路找出来形成一个最短路图,

然后用最小的代价使得最短路图不连通

也就是求这个最短路图的最小割

那怎么建这个最短路图呢?

分别以1和n为源点跑一遍dijkstra,找出每个点到1和n的最短路

设$dis[1][i]$为1到i的最短路,$dis[n][i]$为i到n的最短路

$1->u->v->n$是$1->n$的一条最短路即$dis[1][u]+w[u->v]+dis[n][v]=dis[1][n]$

那么,u->v是1->n最短路上的一条边,加入最短路图中

(由于代码被某人嫌弃太乱,所以对dijkstra和dinic封装了一下...)

•代码

(未封装版)

 #include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
#define INF 0x3f3f3f3f3f3f3f3f
#define P pair<long long,int>
const int maxn=1e5+;
int n,m;
struct Edge
{
int v;
ll w;
int next;
}de[maxn],fe[maxn],e[maxn]; int head1[maxn],head2[maxn];
int cnt1,cnt2;
void add(int u,int v,ll w)
{
de[++cnt1]={v,w,head1[u]};
head1[u]=cnt1; fe[++cnt2]={u,w,head2[v]};
head2[v]=cnt2;
} ll dis1[maxn],disn[maxn];
bool vis1[maxn],visn[maxn];
priority_queue<P,vector<P>,greater<P> >pq; void dijkstra()
{
while(!pq.empty())
pq.pop();
for(int i=;i<=n;i++)
dis1[i]=INF,vis1[i]=;
dis1[]=;
pq.push(make_pair(,));
while(!pq.empty())
{
int u=pq.top().second;
pq.pop();
if(!vis1[u])
{
vis1[u]=;
for(int i=head1[u];~i;i=de[i].next)
{
int v=de[i].v;
dis1[v]=min(dis1[v],dis1[u]+de[i].w);
pq.push(make_pair(dis1[v],v));
}
}
} while(!pq.empty())
pq.pop();
for(int i=;i<=n;i++)
disn[i]=INF,visn[i]=;
disn[n]=; pq.push(make_pair(,n));
while(!pq.empty())
{
int u=pq.top().second;
pq.pop();
if(!visn[u])
{
visn[u]=;
for(int i=head2[u];~i;i=fe[i].next)
{
int v=fe[i].v;
disn[v]=min(disn[v],disn[u]+fe[i].w);
pq.push(make_pair(disn[v],v));
}
}
}
} int head[maxn],cnt;
int cur[maxn],d[maxn];
void addEdge(int u,int v,ll w)
{
e[++cnt]={v,w,head[u]};
head[u]=cnt; e[++cnt]={u,,head[v]};
head[v]=cnt;
} bool bfs()
{
queue<int> q;
for(int i=;i<=n;i++)
d[i]=-;
d[]=;
q.push();
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v;
if(d[v]==-&&e[i].w>)
{
d[v]=d[u]+;
q.push(v);
}
}
}
return d[n]!=-;
} ll dfs(int u,ll flow)
{
ll nowflow=;
if(u==n) return flow;
for(int i=cur[u];~i;i=e[i].next)
{
cur[u]=i;
int v=e[i].v;
if(d[v]==d[u]+&&e[i].w>)
{
ll k=dfs(v,min(flow-nowflow,e[i].w));
if(k)
{
nowflow+=k;
e[i].w-=k;
e[i^].w+=k;
if(nowflow==flow)
break;
}
}
}
if(!nowflow) d[u]=-;
return nowflow;
} ll Dinic()
{
ll ans=;
while(bfs())
{
for(int i=;i<=n;i++)
cur[i]=head[i]; ans+=dfs(,INF);
}
return ans;
} void Init()
{
mem(head1,-);
mem(head2,-);
mem(head,-);
cnt1=cnt2=cnt=-;
} int main()
{
// freopen("C:\\Users\\14685\\Desktop\\C++workspace\\in&out\\contest","r",stdin);
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
Init();
for(int i=;i<=m;i++)
{
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
add(u,v,w);
} dijkstra(); for(int u=;u<=n;u++)
{
for(int i=head1[u];~i;i=de[i].next)
{
int v=de[i].v;
if(dis1[u]+disn[v]+de[i].w==dis1[n])
{
// printf("***%d %d %d\n",u,v,de[i].w);
addEdge(u,v,de[i].w);
}
}
} printf("%lld\n",Dinic());
}
}

(封装版)

 #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pli pair<ll,int>
#define INF 0x3f3f3f3f3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=1e5+;
int n,m;
struct Edge
{
int v;
ll w;
int next;
}G[maxn<<],e[maxn<<];
int dhead[maxn],dcnt;
void addEdge(int u,int v,ll w)
{
G[++dcnt]={v,w,dhead[u]};
dhead[u]=dcnt;
} struct Dij
{
ll dis[][maxn];
bool vis[maxn];
priority_queue<pli,vector<pli>,greater<pli> > q;
void dij(int s,int n,bool ok)
{
for(int i=;i<=n;i++)
dis[ok][i]=INF,vis[i]=;
dis[ok][s]=;
q.push({,s});
while(!q.empty())
{
int u=q.top().second;
q.pop();
if(vis[u])
continue;
vis[u]=;
for(int i=dhead[u];~i;i=G[i].next)
{
///偶数是正向边,ok=true是正向边
if(ok && i&)
continue;
///奇数是反向边,ok=false是反向边
if(!ok && !(i&))
continue; int v=G[i].v;
ll w=G[i].w;
if(dis[ok][v]>dis[ok][u]+w)
{
dis[ok][v]=dis[ok][u]+w;
if(!vis[v])
q.push({dis[ok][v],v});
}
}
}
}
}dij; int head[maxn],cnt;
void add(int u,int v,ll w)
{
e[++cnt]={v,w,head[u]};
head[u]=cnt;
}
struct Dinic
{
int cur[maxn],d[maxn];
int s=,t=n;
bool bfs()
{
queue<int> q;
for(int i=;i<=n;i++)
d[i]=-;
d[]=;
q.push();
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].v;
if(d[v]==-&&e[i].w>)
{
d[v]=d[u]+;
q.push(v);
}
}
}
return d[n]!=-;
} ll dfs(int u,ll flow)
{
ll nowflow=;
if(u==n) return flow;
for(int i=cur[u];~i;i=e[i].next)
{
cur[u]=i;
int v=e[i].v;
if(d[v]==d[u]+&&e[i].w>)
{
ll k=dfs(v,min(flow-nowflow,e[i].w));
if(k)
{
nowflow+=k;
e[i].w-=k;
e[i^].w+=k;
if(nowflow==flow)
break;
}
}
}
if(!nowflow) d[u]=-;
return nowflow;
} ll din()
{
ll ans=;
while(bfs())
{
for(int i=;i<=n;i++)
cur[i]=head[i]; ans+=dfs(,INF);
}
return ans;
}
}_din; void Init()
{
mem(dhead,-);
dcnt=-;
mem(head,-);
cnt=-;
} int main()
{
int T;
scanf("%d",&T);
while(T--)
{
Init();
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
///跑1到其他点的最短路 加正向边
addEdge(u,v,w);
///跑n到其他点的最短路 加反向边
addEdge(v,u,w);
} dij.dij(,n,true);
dij.dij(n,n,false); for(int u=;u<=n;u++)
{
for(int i=dhead[u];~i;i=G[i].next)
{
int v=G[i].v;
ll w=G[i].w;
if(dij.dis[][u]+dij.dis[][v]+w==dij.dis[][n])
{
add(u,v,w);
add(v,u,);
}
}
}
printf("%lld\n",_din.din());
}
}

hdu 6852Path6(最短路+最小割)的更多相关文章

  1. 【bzoj1266】[AHOI2006]上学路线route 最短路+最小割

    题目描述 可可和卡卡家住合肥市的东郊,每天上学他们都要转车多次才能到达市区西端的学校.直到有一天他们两人参加了学校的信息学奥林匹克竞赛小组才发现每天上学的乘车路线不一定是最优的. 可可:“很可能我们在 ...

  2. HDU 5889 Barricade(最短路+最小割)

    http://acm.hdu.edu.cn/showproblem.php?pid=5889 题意: 给出一个图,帝国将军位于1处,敌军位于n处,敌军会选择最短路到达1点.现在帝国将军要在路径上放置障 ...

  3. HDU 5889 Barricade(最短路+最小割水题)

    Barricade Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total ...

  4. hdu 3870(平面图最小割转最短路)

    Catch the Theves Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65768/32768 K (Java/Others) ...

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

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

  6. hdu 4289 Control(最小割 + 拆点)

    http://acm.hdu.edu.cn/showproblem.php?pid=4289 Control Time Limit: 2000/1000 MS (Java/Others)    Mem ...

  7. 【求出所有最短路+最小割】【多校第一场】【G题】

    题意 A从1要追在N的 B 只能走最短的路 问B最少切断多少条路可以让A不能过来 问B最多切断多少条路A还是能过来 对于1 求出1到N的所有最短路的路径,对其求最小割 对于2 求出长度最小的最短路即可 ...

  8. BZOJ1266 AHOI2006上学路线(最短路+最小割)

    求出最短路后找出可能在最短路上的边,显然割完边后我们需要让图中这样的边无法构成1到n的路径,最小割即可,非常板子. #include<iostream> #include<cstdi ...

  9. HDU 4859 海岸线(最小割+最大独立点权变形)

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题意: 欢迎来到珠海!由于土地资源越来越紧张,使得许多海滨城市都只能依靠填海来扩展市区以求发展.作为Z市的 ...

随机推荐

  1. oracle编写分页过程

    有了上面的基础,相信大家可以完成分页存储过程了,要求,请大家编写一个存储过程,要求可以输入表名.每页显示记录数.当前页.排序字段(deptno降序).返回总记录数,总页数和返回结果集. 把一个字符串, ...

  2. java 读取文内容(text,html)

    1.将前端上传的html文件全部读取出来,并用string字符串返回出去解析的内容 public static String openFile(MultipartFile file) { try { ...

  3. maven 标签: 项目管理软件 2016-09-11 22:29 323人阅读 评论(24) 收藏

    开始接触itoo的java项目之后,也就开始接触maven,搭建环境中有一个步骤是配置maven和jboss,当时知道jboss是用来部署我们的项目的,但是maven就只知道一个更新maven,那么, ...

  4. 免费的容器架构可视化工具 | 阿里云应用高可用服务 AHAS 发布重大新特性

    工具下载链接:点这里.活动发布链接:点这里. 采用容器服务后,了解容器之间的关系及依赖是一个比较有挑战的问题.容器化改造后的实际架构模型可能与预想的架构存在较大的差异,架构师或系统运维人员需要精确地了 ...

  5. spider csdn blog part II

    继续上次的笔记, 继续完善csdn博文的提取. 发现了非常好的模块. html2docx 结果展示: 运行之后, 直接生成docx文档. 截个图如下: 结果已经基本满意了!!! 在编写过程中的一些感想 ...

  6. WebGL three.js学习笔记 加载外部模型以及Tween.js动画

    WebGL three.js学习笔记 加载外部模型以及Tween.js动画 本文的程序实现了加载外部stl格式的模型,以及学习了如何把加载的模型变为一个粒子系统,并使用Tween.js对该粒子系统进行 ...

  7. LightOJ 1341 Aladdin and the Flying Carpet【整数分解】

    题目链接: http://lightoj.com/login_main.php?url=volume_showproblem.php?problem=1341 题意: 给定一个数,将其拆分成两个数的乘 ...

  8. Redis源码解析:07压缩列表

    压缩列表(ziplist)是列表键和哈希键的底层实现之一.当列表键只包含少量列表项,并且每个列表项要么是小整数值,要么是长度较短的字符串时:或者当哈希键只包含少量键值对,并且每个键值对的键和值要么是小 ...

  9. @loj - 2480@ 「CEOI2017」One-Way Streets

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一张 n 个点 m 条边的无向图,现在想要把这张图定向. 有 ...

  10. HZOJ Drink

    神仙题,打了个whs式暴力卡常卡A了(我没脸),正解还是要打的,然而作者的题解看不懂…… Drink: 看惯了罗马音的小朋友们都会知道r发l的音,题目名:D Link. 每次修改都会改变O( N ^  ...