HDU 3416:Marriage Match IV(最短路+最大流)
http://acm.hdu.edu.cn/showproblem.php?pid=3416
题意:给出n个点m条边,边信息分别是两个端点和一个费用,再给出一个起点和一个终点,问从起点到终点的完全不相同的最短路径有多少条。(即走过的边不能在走过了)。
思路:因为是在网络流专题里面,所以一开始以为先用SPFA跑一个最小费用出来,然后再用最小费用最大流(然而是最小费用最大流是满足最大流的前提下再考虑最小费用的,很明显是行不通的)。后来想要保证路径不重复,就跑完一次最短路就删除路径(好像也是行不通)。然后只能看下题解了= =。
从起点到终点跑一次SPFA,再从终点到起点跑一次SPFA,这里第一次SPFA跑出来的距离数组是d[0],第二次跑出来的是d[1],如果d[0][u] + w(u, v) + d[1][v] == d[0][T],那么这条w(u,v)边一定是最短路上的边。这里说说我对这个定理的看法:d[0][u]是从起点到u点的最短距离,而d[1][v]是从v到终点的最短距离,那么如果加上这条边刚好等于从起点到终点的最短距离,那么这条边就必定是最短路的边,嗯。好像很明显。然后将这些必定在最短路上的边建起网络,容量是1,跑一遍从起点到终点的最大流,就是最终答案了。这样就符合最大流的思想了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
#define N 1010
#define M 200010
#define INF 0x3f3f3f3f
struct Edge {
int v, cap, nxt;
Edge () {}
Edge (int v, int nxt, int cap) : v(v), nxt(nxt), cap(cap) {}
} edge[M], e[M];
int cur[N], pre[N], gap[N], dis[N], d[][N], vis[N], head[N], h[N], uu[M], vv[M], ww[M], tot, tt, S, T, n, m; void Add(int u, int v, int cap, int tag) {
if(tag == ) { e[tt] = Edge(v, h[u], cap); h[u] = tt++; }
else { edge[tot] = Edge(v, head[u], cap); head[u] = tot++; edge[tot] = Edge(u, head[v], ); head[v] = tot++; }
} void SPFA(int st, int ed, int id) {
for(int i = ; i <= n; i++) d[id][i] = INF;
memset(vis, , sizeof(vis));
queue<int> que; que.push(st);
vis[st] = ; d[id][st] = ;
while(!que.empty()) {
int u = que.front(); que.pop(); vis[u] = ;
for(int i = h[u]; ~i; i = e[i].nxt) {
int v = e[i].v, w = e[i].cap;
if(d[id][v] > d[id][u] + w) {
d[id][v] = d[id][u] + w;
if(vis[v]) continue;
que.push(v); vis[v] = ;
}
}
}
} void BFS() {
memset(dis, INF, sizeof(dis));
memset(gap, , sizeof(gap));
queue<int> que; que.push(T);
dis[T] = ; gap[]++;
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = head[u]; ~i; i = edge[i].nxt) {
int v = edge[i].v;
if(dis[v] != INF) continue;
dis[v] = dis[u] + ;
gap[dis[v]]++;
que.push(v);
}
}
} int ISAP(int n) {
BFS();
memcpy(cur, head, sizeof(cur));
int u = pre[S] = S, ans = , flow, i, index;
while(dis[S] < n) {
if(u == T) {
flow = INF;
for(i = S; i != T; i = edge[cur[i]].v)
if(flow > edge[cur[i]].cap) flow = edge[cur[i]].cap, index = i;
for(i = S; i != T; i = edge[cur[i]].v)
edge[cur[i]].cap -= flow, edge[cur[i]^].cap += flow;
u = index; ans += flow;
}
for(i = cur[u]; ~i; i = edge[i].nxt) if(edge[i].cap > && dis[edge[i].v] + == dis[u]) break;
if(~i) { cur[u] = i; pre[edge[i].v] = u; u = edge[i].v; }
else {
if(--gap[dis[u]] == ) break;
int md = n + ;
for(i = head[u]; ~i; i = edge[i].nxt)
if(dis[edge[i].v] < md && edge[i].cap > ) md = dis[edge[i].v], cur[u] = i;
gap[dis[u] = md + ]++;
u = pre[u];
}
}
return ans;
} int main() {
int t;
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
int edgenum = ;
for(int i = ; i <= m; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
//if(u == v) continue;
edgenum++; uu[edgenum] = u; vv[edgenum] = v; ww[edgenum] = w;
}
scanf("%d%d", &S, &T);
memset(h, -, sizeof(h)); tt = ;
for(int i = ; i <= edgenum; i++) Add(uu[i], vv[i], ww[i], );
SPFA(S, T, );
memset(h, -, sizeof(h)); tt = ;
for(int i = ; i <= edgenum; i++) Add(vv[i], uu[i], ww[i], );
SPFA(T, S, );
memset(head, -, sizeof(head)); tot = ;
for(int i = ; i <= edgenum; i++)
if(d[][uu[i]] + d[][vv[i]] + ww[i] == d[][T]) Add(uu[i], vv[i], , ); // 容量设成1.而不是ww
int ans = ISAP(n + );
printf("%d\n", ans);
}
return ;
}
HDU 3416:Marriage Match IV(最短路+最大流)的更多相关文章
- HDU 3416 Marriage Match IV (最短路建图+最大流)
(点击此处查看原题) 题目分析 题意:给出一个有n个结点,m条单向边的有向图,问从源点s到汇点t的不重合的最短路有多少条,所谓不重复,意思是任意两条最短路径都不共用一条边,而且任意两点之间的边只会用一 ...
- HDU 3416 Marriage Match IV (Dijkstra+最大流)
题意:N个点M条边的有向图,给定起点S和终点T,求每条边都不重复的S-->T的最短路有多少条. 分析:首先第一步需要找出所有可能最短路上的边.怎么高效地求出呢?可以这样:先对起点S,跑出最短路: ...
- HDU 3416 Marriage Match IV (最短路径&&最大流)
/*题意: 有 n 个城市,知道了起点和终点,有 m 条有向边,问从起点到终点的最短路一共有多少条.这是一个有向图,建边的时候要注意!!解题思路:这题的关键就是找到哪些边可以构成最短路,其实之前做最短 ...
- hdu 3416 Marriage Match IV (最短路+最大流)
hdu 3416 Marriage Match IV Description Do not sincere non-interference. Like that show, now starvae ...
- HDU 3416 Marriage Match IV (最短路径,网络流,最大流)
HDU 3416 Marriage Match IV (最短路径,网络流,最大流) Description Do not sincere non-interference. Like that sho ...
- HDU 3416 Marriage Match IV (求最短路的条数,最大流)
Marriage Match IV 题目链接: http://acm.hust.edu.cn/vjudge/contest/122685#problem/Q Description Do not si ...
- HDU 3416 Marriage Match IV
最短路+最大流 #include<cstdio> #include<cstring> #include<string> #include<cmath> ...
- HDU 3416 Marriage Match IV 【最短路】(记录路径)+【最大流】
<题目链接> 题目大意: 给你一张图,问你其中没有边重合的最短路径有多少条. 解题分析: 建图的时候记得存一下链式后向边,方便寻找最短路径,然后用Dijkstra或者SPFA跑一遍最短路, ...
- HDU 3416 Marriage Match IV(ISAP+最短路)题解
题意:从A走到B,有最短路,问这样不重复的最短路有几条 思路:先来讲选有效边,我们从start和end各跑一次最短路,得到dis1和dis2数组,如果dis1[u] + dis2[v] + cost[ ...
- HDU 3416 Marriage Match IV(最短路,网络流)
题面 Do not sincere non-interference. Like that show, now starvae also take part in a show, but it tak ...
随机推荐
- WPF自定义控件 使用阿里巴巴图标
原文:WPF自定义控件 使用阿里巴巴图标 上一篇介绍了 WPF自定义控件 按钮 的初步使用,在进一步介绍WPF自定义控件 按钮之前,先介绍一下如何在WPF项目中使用阿里巴巴图标,方便以后做示例. 1. ...
- CSharp获取图形文件的读写
C#是微软发布了一个面向对象.开展对.NET Framework上述高级编程语言.并定于占领在微软开发者论坛(PDC)在首演. C#这是微软研究员Anders Hejlsberg最新成就.C#容貌Ja ...
- Spring MVC专题
Spring从3.1版本开始增加了ConfigurableEnvironment和PropertySource: ConfigurableEnvironment Spring的ApplicationC ...
- 【C#/WPF】调节图像的HSL(色相、饱和度、明亮度)
原文:[C#/WPF]调节图像的HSL(色相.饱和度.明亮度) 先说概念: HSL是一种描述颜色的方式(其他颜色描述方式还有大家熟悉的RGB值).HSL三个字母分别表示图像的Hue色相.Saturat ...
- MQTT协议学习及实践(Linux服务端,Android客户端的例子)
前言 MQTT(Message Queuing Telemetry Transport),是一个物联网传输协议,它被设计用于轻量级的发布/订阅式消息传输,旨在为低带宽和不稳定的网络环境中的物联网设备提 ...
- v-charts显示标题
使用v-charts的时候,如果要显示标题需要以下操作 1. 加入:title props <ve-pie :title="chartTitle" :data="c ...
- jquery模拟飞秋
<!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
- Windows7,程序兼容助手:这个程序可能安装不正确(做注册表里设置白名单,软件自身的名字不能带setup)
Windows上有一个很奇怪的一个现象,一个exe只要名字里面带了setup\install之类的,打开exe后立即退出就会弹出下面的窗口. 解决方法: 方法一.更改exe的名字,去掉setup\in ...
- qmake 时复制文件(自动在编译前做一些操作,且写在.pro文件里)
有时在编译前需要准备一些文件,例如修改了 QtCreator 的编译输出目录: Build & Run > Default build directory,使用 Promote 后需要在 ...
- SQL Server 游标运用:查看一个数据库所有表大小信息(Sizes of All Tables in a Database)
原文:SQL Server 游标运用:查看一个数据库所有表大小信息(Sizes of All Tables in a Database) 一.本文所涉及的内容(Contents) 本文所涉及的内容(C ...