http://acm.hdu.edu.cn/showproblem.php?pid=4034

给出最短路,问最少有几条边,floyd加一个变量记录该边是否取

如果满足dis[i][k]+dis[k][j]==dis[i][j],那么i到j这条边就不取

如果出现dis[i][k]+dis[k][j]<dis[i][j]则与最短路条件矛盾

#include <iostream>
#include <cstdio>
using namespace std ;
const int INF=0xffffffff ;
int dis[105][105],n ;
int vis[105][105] ;
int floyd()
{
    for(int k=1 ;k<=n ;k++)
    {
        for(int i=1 ;i<=n ;i++)
        {
            for(int j=1 ;j<=n ;j++)
            {
                if(i==j || i==k || j==k)continue ;
                if(dis[i][k]+dis[k][j]<dis[i][j])
                    return 0;
                if(dis[i][k]+dis[k][j]==dis[i][j])
                    vis[i][j]=0 ;
            }
        }
    }
    return 1 ;
}
int main()
{
    int t ;
    scanf("%d",&t) ;
    int cas=1 ;
    while(t--)
    {
        scanf("%d",&n) ;
        for(int i=1 ;i<=n ;i++)
        {
            for(int j=1 ;j<=n ;j++)
            {
                scanf("%d",&dis[i][j]) ;
            }
        }
        printf("Case %d: ",cas++) ;
        for(int i=0 ;i<105 ;i++)
            for(int j=0 ;j<105 ;j++)
                vis[i][j]=1 ;
        int flag=floyd() ;
        int ans=0 ;
        for(int i=1 ;i<=n ;i++)
        {
            for(int j=1 ;j<=n ;j++)
            {
                if(!dis[i][j])
                {
                    vis[i][j]=0 ;
                }
            }
        }
        for(int i=1 ;i<=n ;i++)
            for(int j=1 ;j<=n ;j++)
                if(vis[i][j])ans++ ;
        if(flag)
            printf("%d\n",ans) ;
        else puts("impossible") ;
    }
    return 0 ;
}
View Code