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 ",ans) ; else puts("impossible") ; } return 0 ; }