hdu4034 逆向算

来源:互联网 发布:二进制数据压缩算法 编辑:程序博客网 时间:2024/05/16 09:56

题目描述:给你一个n*n矩阵来表示一个图,矩阵的每个元素gij都表示i点到j点的最短路,其中对角线元素总是0。问满足这个矩阵的图的最少边数是多少,若不存在,则输出impossible。

显然,边数最多的情况是每两点之间都有最短的直边相连,边数最多为n2-n,在每两点都有最短直边相连情况下,我们以一一删去多余的边,最后就是最终结果。 考虑:若gij = gik + gkj ,i 与 j的这条边可以删去,因为i到j的最短路gij可以由gik+gkj转移来;若gij > gik + gkj ,则说明矩阵的gij并不是最短路,存在矛盾,此时则不存在这样的图,输出impossible。

还有,需要注意的是,每条边最多被删去一次,所以当一条边被删去时,需要标记,防止多次被删。

#include<cstdio>#include<iostream>#include<cstring>#include<cmath>const int LEN=105;int path[LEN][LEN], vis[LEN][LEN], dis[LEN], n;int floyd(){    int ans=0;    memset(vis, 0, sizeof(vis));for (int k=0; k<n; k++)    {        for (int i=0; i<n; i++)        {            for (int j=0; j<n; j++)            {                if ( i!=j && j!=k && i!=k )                {                    if ( path[i][j]==path[i][k]+path[k][j] && !vis[i][j])                    {                        vis[i][j]=1;                        ans++;                        //break;                    }                    if ( path[i][j]>path[i][k]+path[k][j] )                        return -1;                }            }        }    }    return ans;}int main(){    int T, k;    scanf("%d", &T);    for (k=1; k<=T; k++)    {        scanf("%d", &n);        for (int i=0; i<n; i++)        {            for (int j=0; j<n; j++)            {                scanf("%d", &path[i][j]);            }        }        int ans=floyd();        printf("Case %d: ", k);        if ( ans==-1 )        {            printf("impossible\n");        }        else        {            printf("%d\n", n*(n-1)-ans);        }    }    //system("pause");    return 0;}


原创粉丝点击