zoukankan      html  css  js  c++  java
  • (原创)有向图的传递闭包问题

    Description
    KJZ的师弟师妹们最近在学习离散数学,于是他决定出一道简单的图论知识考考大家! 在这里他向大家介绍了一个叫做传递闭包的概念。 传递闭包就是,在集合X上的二元关系R的传递闭包是包含R的X上的最小的传递关系。 那么什么事有向图的传递闭包呢? 对于有向图G(V,E)的传递闭包即是G(V,E),其中E{(i,j):图G中包含一条由i到j的路径}。 读到这里的你,如果是一头雾水的话,证明你集合论学的不是很好,一定要认真听离散数学的课程喔! 但是KJZ是一名尽职的师兄,他在这里通过一道题目,向你通俗易懂的介绍什么是有向图的传递闭包。
    Input
    每个输入只有一组 每组输入第一行包括一个整数N(1<=N<=300) 接下来N行N列,代表一个矩阵G 如果G[i][j] = 1,代表i有一条边连向j 如果G[i][j] = 0,代表i没有边连向j 且对于1~N,G[i][i]必定等于1 接下来一个数字Q,代表有Q次查询 (1<=Q<=100000) 接下来有Q行,每行两个数字u,v
    Output
    对于每个查询u,v,输出一行,如果u能走到v,输出1,否则输出0
    Sample Input 1
    3
    1 1 0
    0 1 1
    0 0 1
    5
    1 1
    1 3
    2 3
    3 2
    3 1
    Sample Output 1
    1
    1
    1
    0
    0
    解题思路:这道题的思路非常巧妙,就是利用Floyd的最短路径,假设能找到“最短路径”则证明是连通的,不能则证明不联通;
    Floyd算法大概思想:依次扫描每一点(k),并以该点作为中介点,计算出通过k点的其他任意两点(i,j)的最短距离,这就是floyd算法的精髓
    也就是说起点i 直接到达终点 j 最短 还是从i 出发 经过中间 若干点 k  到达 j 最短;
    实现只需要三个循环:
      
    1 for(int k = 1 ; k  <= N ;k++)      //k表示的是中间经过的点,这个循环一定要放在最外面
    2    for(int i  = 1 ; i <= N; i++)
    3        for(int j = 1  ; j <= N ;j++)
    4           dp[i][j] = min(dp[i][j],d[i][k]+d[k][j]);      //不断取“最小”;

    回归这道题,我们也可以以这种思想,从该起点 i 出发,看是否经过中间 k 点 ,能到达 j点;或者从i 直接到达 j 点;

    代码如下:

     1 #include<iostream>
     2 using namespace std;
     3 
     4 
     5 int N;
     6 int Q;
     7 int x ,y;
     8 int G[305][305];
     9 int map[305][305];
    10 int main()
    11 {
    12     cin>>N;
    13     for(int i = 1 ;i <= N;i++)
    14     {
    15         for(int j = 1 ; j <= N;j++)
    16         {
    17             cin>>G[i][j];           //输入这个矩阵
    18         }
    19     }
    20       
    21     for(int k = 1 ; k <= N ;k++)     //这个中间点的循环一定要放在最外面;
    22     {
    23         for(int i = 1 ;i <= N; i++)
    24         {
    25             for(int j = 1 ; j <= N;j++)
    26             {
    27                 if(G[i][j]==1||G[i][k]==1&&G[k][j]==1) 
    28                            //直接连通或者间接经过其他点连通;
    29                 {
    30                     map[i][j] = 1;  //将这两点连通;
    31                  } 
    32             }
    33         }
    34     }
    35     cin>>Q;
    36     for(int i = 1 ; i <= Q ;i++)
    37     {
    38         cin>>x>>y;
    39         if(map[x][y]==1)    //判断两点是否连通
    40         cout<<1<<endl;
    41         else cout<<0<<endl;
    42     }
    43     return 0;
    44 }
     
  • 相关阅读:
    WCF 第八章 安全 确定替代身份(中)使用AzMan认证
    WCF 第八章 安全 总结
    WCF 第八章 安全 因特网上的安全服务(下) 其他认证模式
    WCF Membership Provider
    WCF 第八章 安全 确定替代身份(下)模仿用户
    WCF 第八章 安全 因特网上的安全服务(上)
    WCF 第九章 诊断
    HTTPS的七个误解(转载)
    WCF 第八章 安全 日志和审计
    基于比较的排序算法集
  • 原文地址:https://www.cnblogs.com/yewanting/p/10592004.html
Copyright © 2011-2022 走看看