• hdu 4034 【floyed变形】


    Graph

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)
    Total Submission(s): 2485    Accepted Submission(s): 1270


    Problem Description
    Everyone knows how to calculate the shortest path in a directed graph. In fact, the opposite problem is also easy. Given the length of shortest path between each pair of vertexes, can you find the original graph?
     
    Input
    The first line is the test case number T (T ≤ 100).
    First line of each case is an integer N (1 ≤ N ≤ 100), the number of vertexes.
    Following N lines each contains N integers. All these integers are less than 1000000.
    The jth integer of ith line is the shortest path from vertex i to j.
    The ith element of ith line is always 0. Other elements are all positive.
     
    Output
    For each case, you should output “Case k: ” first, where k indicates the case number and counts from one. Then one integer, the minimum possible edge number in original graph. Output “impossible” if such graph doesn't exist.

     
    Sample Input
    3 3 0 1 1 1 0 1 1 1 0 3 0 1 3 4 0 2 7 3 0 3 0 1 4 1 0 2 4 2 0
     
    Sample Output
    Case 1: 6 Case 2: 4 Case 3: impossible
     
     



    题意:读入矩阵,矩阵中存储的是i到j的最短路径,问,原图中的最小路径总数为多少?不存在原图,按题目输出

    思路:floyed的变形。既然矩阵中存储的已经是最短路径,那么此矩阵中每条路径都必然满足最优值,比如第三个样例,直接从1到3的最短路径是4,而通过1到2(最短路径是1)再从2到3(最短路径是2)总的最短路径是3,比直接从1到3更短,不满足题目所说的条件,输出“impossible",所以,此样例给我们提供了一种思路:比较直接到达的最短路径w[i][j]和通过一个中转点k的路径w[i][k]+w[k][j]的值的大小。如果二者相等,说明直接到达的这条边取消也不影响原图,如果前者大于后者,说明不满足条件。记得定义一个标记数组,对已经访问过的点进行标记。

    #include<stdio.h>
    #include<string.h>
    #define N 110
    int w[N][N],vis[N][N],n,sum,flag,ans;
    int Count()
    {
        int i,j,k;
        for(i = 1; i <= n; i ++)
            for(j = 1; j <= n; j ++)
                for(k = 1; k <= n; k ++)
                {
                    if(i!=j&&j!=k&&k!=i)//自身到自身的情况不用考虑 
                    {
                        if(w[i][j] == w[i][k] + w[k][j]&&!vis[i][j])
                        {
                            vis[i][j] = 1;//如果满足最短路径的条件,标记为访问过 
                            ans ++;//可取消的边数增加 
                        }
                        if(w[i][j] > w[i][k] + w[k][j])//如果不满足最短路径的条件,结束函数 
                            return 0;
                    }    
                }
        return 1;
    }
    int main()
    {
        int t,i,j;
        scanf("%d",&t);
        int t2 = 0;
        while(t--)
        {
            scanf("%d",&n);
            memset(vis,0,sizeof(vis));//标记数组 
            for(i = 1; i <= n; i ++)
                for(j = 1; j <= n; j ++)
                {
                    scanf("%d",&w[i][j]);
                    if(i == j)//自身到自身的下标标记为已经访问过 
                        vis[i][j] = 1;
                }
            sum = n*n-n;//总的边数 
            ans = 0;
            printf("Case %d: ",++t2);
            if(Count())
                printf("%d
    ",sum-ans);//总边数减去可以取消的边数就是原图最小的边数 
            else
                printf("impossible
    ");
        }
        return 0;
    }

     

  • 相关阅读:
    C#打开SDE数据库的几种方式
    关于DataGridView
    细说Sql Server中的视图(下)转载
    细说Sql Server中的视图(上)转载
    细说Sql Server中的视图
    Ajax实现原理,代码封装
    无限级下拉菜单(树形菜单,二级菜单)
    无限循环轮播图之JS部分(原生JS)
    无限循环轮播图之结构布局(原生JS)
    无限循环轮播图之运动框架(原生JS)
  • 原文地址:https://www.cnblogs.com/hellocheng/p/7510804.html
Copyright © 2020-2023  润新知