<题目链接>

题目大意:

给你一张图,问你其中没有边重合的最短路径有多少条。

解题分析:

建图的时候记得存一下链式后向边,方便寻找最短路径,然后用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 【最短路】(记录路径)+【最大流】的更多相关文章

  1. HDU 3416 Marriage Match IV (最短路建图+最大流)

    (点击此处查看原题) 题目分析 题意:给出一个有n个结点,m条单向边的有向图,问从源点s到汇点t的不重合的最短路有多少条,所谓不重复,意思是任意两条最短路径都不共用一条边,而且任意两点之间的边只会用一 ...

  2. hdu 3416 Marriage Match IV (最短路+最大流)

    hdu 3416 Marriage Match IV Description Do not sincere non-interference. Like that show, now starvae ...

  3. HDU 3416 Marriage Match IV (最短路径,网络流,最大流)

    HDU 3416 Marriage Match IV (最短路径,网络流,最大流) Description Do not sincere non-interference. Like that sho ...

  4. HDU 3416 Marriage Match IV (求最短路的条数,最大流)

    Marriage Match IV 题目链接: http://acm.hust.edu.cn/vjudge/contest/122685#problem/Q Description Do not si ...

  5. HDU 3416 Marriage Match IV(ISAP+最短路)题解

    题意:从A走到B,有最短路,问这样不重复的最短路有几条 思路:先来讲选有效边,我们从start和end各跑一次最短路,得到dis1和dis2数组,如果dis1[u] + dis2[v] + cost[ ...

  6. HDU 3416 Marriage Match IV(最短路,网络流)

    题面 Do not sincere non-interference. Like that show, now starvae also take part in a show, but it tak ...

  7. hdu 3416 Marriage Match IV 【 最短路 最大流 】

    求边不可重复的最短路条数 先从起点到终点用一次dijkstra,再从终点到起点用一次dijkstra,来判断一条边是否在最短路上 如果在,就将这条边的两个端点连起来,容量为1 再跑一下dinic(), ...

  8. HDU 3416 Marriage Match IV dij+dinic

    题意:给你n个点,m条边的图(有向图,记住一定是有向图),给定起点和终点,问你从起点到终点有几条不同的最短路 分析:不同的最短路,即一条边也不能相同,然后刚开始我的想法是找到一条删一条,然后光荣TLE ...

  9. HDU 3416 Marriage Match IV

    最短路+最大流 #include<cstdio> #include<cstring> #include<string> #include<cmath> ...

随机推荐

  1. python1113

    点点滴滴才可以来开距离,人与人的差距是在点点滴滴中拉开的 break 语句可以跳出 for 和 while 的循环体的当前循环 continue语句被用来告诉Python跳过当前循环块中的剩余语句,然 ...

  2. Confluence 6 配置验证码(Captcha)来防止垃圾

    如果你的 Confluence 站点是对公众开放的(允许匿名用户使用,添加评论,创建页面等),你可能会发现你的站点会被自动创建很多垃圾页面,评论或者其他垃圾内容. 你可以配置让 Confluence ...

  3. (一)STL体系结构基础介绍

    一.STL六大部件 容器(Containers):存放元素,内存由分配器搞定 分配器(Allocator):支持容器的内存分配 算法:操作容器元素的函数.与OO不同(面向对象将元素与函数放到一个类里) ...

  4. Java的家庭记账本程序(B)

    日期:2019.2.3 博客期:029 星期日 看看今天想先完成jsp的连接操作,所以首先意识到自己的程序中,管理员可以对成员进行冻结.解封操作,所以先回去补了一下数据库的内容!成员的内容里多了一项i ...

  5. Mycat配置文件详解及全局序列号

    来详细的看看 mycat的配置文件,更多信息请查看:mycat权威指南. schema.xml: Schema.xml 作为 MyCat 中重要的配置文件之一,管理着 MyCat 的逻辑库.表.分片规 ...

  6. Brup Suite 渗透测试笔记(五)

    之前章节记到Burp Intruder功能区,接上次笔记 一.首先说再展开说说Brup Intruder功能, 1.标识符枚举Web应用程序经常使用标识符来引用用户账户,资产数据信息. 2.提取有用的 ...

  7. C++ Primer 笔记——函数

    1.函数内的局部静态对象在程序的执行路径第一次经过对象定义语句的时候初始化,并且直到程序终止才被销毁,在此期间即使对象所在的函数结束执行也不会对它有影响. size_t get_count() { ; ...

  8. python爬虫点触验证码的识别思路(图片版)

  9. C#递归拷贝文件删除文件

    拷贝文件及子文件,最后一个参数排除,哪个不要删除.(其实就是移动的效果) //拷贝文件及子文件 public static void CopyDirectory(string src, string ...

  10. python虚拟环境搭建

    1.安装python环境 2.检查pip 3.pip install virtualenv 4.创建测试:virtualenv  testvir 5.pip install virtualenvwra ...