HDU 3416 Marriage Match IV 【最短路】(记录路径)+【最大流】
<题目链接>
题目大意:
给你一张图,问你其中没有边重合的最短路径有多少条。
解题分析:
建图的时候记得存一下链式后向边,方便寻找最短路径,然后用Dijkstra或者SPFA跑一遍最短路,从终点开始DFS,找出最短路径上所有的边,然后将其加入网络,所有边的容量置为1,以起点为源点,终点为汇点,跑一遍最大流,求出的结果即为最短路的数量。
Dijkstra+Dinic版:
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; ; ; const int INF = 0x3f3f3f3f; int n, m, st, ed, cnt, cnt1; int head[N], head1[N], dep[N], tail[N]; bool vis[N]; struct Edge{ int u, v, w, next, next1; }edge[M<<], edge1[M<<]; struct Node{ int index,dist; bool operator < (const Node &tmp )const{ return dist>tmp.dist; } }node[M<<]; void init(){ cnt = ,cnt1 = ; memset(head, -, sizeof head); memset(head1, -, sizeof head1); memset(tail, -, sizeof tail); } void addedge(int u, int v, int w){ //建图,跑最短路 edge[cnt].u = u; edge[cnt].v = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt; edge[cnt].next1 = tail[v]; //tail[]数组相当于是反向的head[]数组,链式后向边,用来寻找最短路径上的边 tail[v] = cnt++; } void addedge1(int u, int v, int w){ //建图,跑最大流 edge1[cnt1].u = u; edge1[cnt1].v = v; edge1[cnt1].w = w; edge1[cnt1].next = head1[u]; head1[u] = cnt1++; //正向弧 edge1[cnt1].v = u; edge1[cnt1].u = v; edge1[cnt1].w = ; edge1[cnt1].next = head1[v]; head1[v] = cnt1++; //反向弧 } int Dij(){ priority_queue<Node>q; ;i<=n;i++) vis[i] = false,node[i].index=i,node[i].dist=INF; node[st].dist=; q.push(node[st]); while(!q.empty()){ int u=q.top().index;q.pop(); if(vis[u])continue; vis[u]=true; for(int i=head[u];~i;i=edge[i].next){ int v = edge[i].v; if(node[v].dist>node[u].dist+edge[i].w){ node[v].dist = node[u].dist+edge[i].w; q.push(node[v]); } } } return node[ed].dist!= INF; } void dfs(int v){ //寻找最短路中的所有边,并将其加入网络 ; i = edge[i].next1){ int u = edge[i].u; //u为该后向边的起始点 if(node[u].dist+edge[i].w == node[v].dist){ //判断该边是否为最短路中的边 addedge1(u, v, ); //如果是的话,就加入网络中,跑最大流 if(!vis[u]){ vis[u] = ; dfs(u); } } } } /*-- Dinic --*/ bool bfs(){ memset(vis, , sizeof vis); memset(dep, -, sizeof dep); queue<int> q; q.push(st); vis[st] = ; dep[st] = ; while(!q.empty()){ int cur = q.front();q.pop(); ; i = edge1[i].next){ int v = edge1[i].v; ){ dep[v] = dep[cur]+; vis[v] = ; q.push(v); } } } ; //如果dep[ed]!=-1,说明仍然存在增广路 } int dfs1(int cur, int flow){ if(cur == ed) return flow; ; && flow > res; i = edge1[i].next){ int v = edge1[i].v; && dep[v] == dep[cur]+){ int x = min(edge1[i].w, flow-res); int f = dfs1(v, x); edge1[i].w-=f; edge1[i^].w+=f; res += f; } } ; return res; } int dinic(){ ,res; while(bfs()){ while(res = dfs1(st, INF)){ sumflow += res; } } return sumflow; } /*-- Dinic --*/ int main(){ int T; scanf("%d", &T); while(T--){ init(); scanf("%d%d", &n, &m); ; i < m; i++){ int u, v, w; scanf("%d%d%d", &u, &v, &w); addedge(u, v, w); } scanf("%d%d", &st, &ed); "); //跑最短路,如果st->ed不可达,则直接输出0 else{ memset(vis,false,sizeof(vis)); //注意,dijkstra要加上这一句,spfa则不用,因为spfa结束后,所有点的vis全部置为false dfs(ed); //找到最短路中的所有边,并将其加入网络 printf("%d\n",dinic()); //根据最短路所有的边求最大流 } } ; }
SPFA+Dinic版:
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; ; ; const int INF = 0x3f3f3f3f; int n, m, st, ed, cnt, cnt1; int head[N], head1[N], dis[N], dep[N], tail[N]; bool vis[N]; struct Edge{ int u, v, w, next, next1; }edge[M<<], edge1[M<<]; void init(){ cnt = ,cnt1 = ; memset(head, -, sizeof head); memset(head1, -, sizeof head1); memset(tail, -, sizeof tail); } void addEdge1(int u, int v, int w){ //建图,跑最短路 edge[cnt].u = u; edge[cnt].v = v; edge[cnt].w = w; edge[cnt].next = head[u]; head[u] = cnt; edge[cnt].next1 = tail[v]; //tail[]数组相当于是反向的head[]数组,链式后向边,用来寻找最短路径上的边 tail[v] = cnt++; } void addEdge2(int u, int v, int w){ //建图,跑最大流 edge1[cnt1].u = u; edge1[cnt1].v = v; edge1[cnt1].w = w; edge1[cnt1].next = head1[u]; head1[u] = cnt1++; //正向弧 edge1[cnt1].v = u; edge1[cnt1].u = v; edge1[cnt1].w = ; edge1[cnt1].next = head1[v]; head1[v] = cnt1++; //反向弧 } int spfa(){ queue<int> q; ; i <= n; i++) vis[i] = ,dis[i] = INF; vis[st] = ; dis[st] = ; q.push(st); while(!q.empty()){ int cur = q.front(); q.pop(); vis[cur] = ; ; i = edge[i].next) { int v = edge[i].v; if(dis[v] > dis[cur]+edge[i].w) { dis[v] = dis[cur]+edge[i].w; if(!vis[v]) { vis[v] = ; q.push(v); } } } } return dis[ed] != INF; } void dfs(int v){ //寻找最短路中的所有边,并将其加入网络 ; i = edge[i].next1){ int u = edge[i].u; //u为该后向边的起始点 if(dis[u]+edge[i].w == dis[v]){ //判断该边是否为最短路中的边 addEdge2(u, v, ); //如果是的话,就加入网络中,跑最大流 if(!vis[u]){ vis[u] = ; dfs(u); } } } } /*-- Dinic --*/ bool bfs(){ memset(vis, , sizeof vis); memset(dep, -, sizeof dep); queue<int> q; q.push(st); vis[st] = ; dep[st] = ; while(!q.empty()){ int cur = q.front();q.pop(); ; i = edge1[i].next){ int v = edge1[i].v; ){ dep[v] = dep[cur]+; vis[v] = ; q.push(v); } } } ; //如果dep[ed]!=-1,说明仍然存在增广路 } int dfs1(int cur, int flow){ if(cur == ed) return flow; ; && flow > res; i = edge1[i].next){ int v = edge1[i].v; && dep[v] == dep[cur]+){ int x = min(edge1[i].w, flow-res); int f = dfs1(v, x); edge1[i].w-=f; edge1[i^].w+=f; res += f; } } ; return res; } int dinic(){ ,res; while(bfs()){ while(res = dfs1(st, INF)){ sumflow += res; } } return sumflow; } /*-- Dinic --*/ int main(){ int T; scanf("%d", &T); while(T--){ init(); scanf("%d%d", &n, &m); ; i < m; i++){ int u, v, w; scanf("%d%d%d", &u, &v, &w); addEdge1(u, v, w); } scanf("%d%d", &st, &ed); "); //跑最短路,如果st->ed不可达,则直接输出0 else{ dfs(ed); //找到最短路中的所有边,并将其加入网络 printf("%d\n",dinic()); //根据最短路所有的边求最大流 } } ; }
2018-11-23
HDU 3416 Marriage Match IV 【最短路】(记录路径)+【最大流】的更多相关文章
- HDU 3416 Marriage Match IV (最短路建图+最大流)
(点击此处查看原题) 题目分析 题意:给出一个有n个结点,m条单向边的有向图,问从源点s到汇点t的不重合的最短路有多少条,所谓不重复,意思是任意两条最短路径都不共用一条边,而且任意两点之间的边只会用一 ...
- 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(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 ...
- hdu 3416 Marriage Match IV 【 最短路 最大流 】
求边不可重复的最短路条数 先从起点到终点用一次dijkstra,再从终点到起点用一次dijkstra,来判断一条边是否在最短路上 如果在,就将这条边的两个端点连起来,容量为1 再跑一下dinic(), ...
- HDU 3416 Marriage Match IV dij+dinic
题意:给你n个点,m条边的图(有向图,记住一定是有向图),给定起点和终点,问你从起点到终点有几条不同的最短路 分析:不同的最短路,即一条边也不能相同,然后刚开始我的想法是找到一条删一条,然后光荣TLE ...
- HDU 3416 Marriage Match IV
最短路+最大流 #include<cstdio> #include<cstring> #include<string> #include<cmath> ...
随机推荐
- Confluence 6 从一个 XML 备份中导入一个空间
有下面 2 中方法可以导入一个空间——通过上传一个文件,或者从你 Confluence 服务器上的一个目录中导入.上传文件仅仅是针对一个小站点的情况.为了取得最好的导入结果,我们推荐你从服务器上的目录 ...
- Confluence 6 服务器的许可证信息
Confluence 6 服务器的许可证信息. https://www.cwiki.us/display/CONFLUENCEWIKI/Managing+your+Confluence+License
- 最短路径之Floyd-warshall算法
哇咔咔,最喜欢这种算法了,算法简单,暴力解决: 可惜数据大点就解决不了问题了: 输入的数据是 第一行第一个数是city的数量n,第二个是路径数t, 接下来n行为a至b的距离 4 81 2 2 1 3 ...
- oracle 12c ORA-01017:invalid username/password; logon denied
Oracle 12C 中,想通过操作系统认证登录Oracle 数据库,有一些要注意的地方.不然就会遇到 ORA-01017:invalid username/password; logon denie ...
- logging模板日志格式
logging模板日志格式 创建loginfo.py模块,然后导入定义的logging配置,即可使用 cat loginfo.py """ logging配置 " ...
- 20165323《Java程序设计》第九周学习总结
一.教材内容学习总结 URL类 1.URL 类是 java.net 包中的一个重要的类,使用 URL 创建对象的应用程序称为客户端程序. 2.一个 URL 对象通常包含最基本的三部分信息:协议.地址和 ...
- Doracle.jdbc.J2EE13Compliant=true
To make the Oracle driver behave in a Java EE-compliant manner, you must define the following JVM pr ...
- RPC远程过程调用实例
什么是RPC RPC 的全称是 Remote Procedure Call 是一种进程间通信方式.它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程 ...
- maven安装和eclipse集成
maven作为一个项目构建工具,在开发的过程中很受欢迎,可以帮助管理项目中的bao依赖问题,另外它的很多功能都极大的减少了开发的难度,下面来介绍maven的安装及与eclipse的集成. maven的 ...
- Java基础知识➣面向对象(八)
概述 Java和C#都是面向对象语言,面向对象编程是目前高级语言习惯的编程模式,与C++编写过程编程而言,面向对象使用起来高效.灵活:面向对象的三个特征:封装.继承和多态. Java面向对象 1.类封 ...