题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4034
题意:
有一个有向图,n个节点。给出两两节点之间的最短路长度,问你原图至少有多少条边。
如果无解,输出"impossible"。
题解:
因为在floyd中:
if(dis[i][k] + dis[k][j] < dis[i][j])
dis[i][j] = dis[i][k] + dis[k][j];
所以对于原图再跑一遍floyd。
如果出现dis[i][k] + dis[k][j] < dis[i][j]的情况,则给出的邻接矩阵不是最短路,无解。
对于三个点i,j,k,如果有dis[i][j] == dis[i][k] + dis[k][j],则(i,j)这条边一定可以舍去。
因为如果其他的最短路径要用到(i,j)边的话,用(i,k)+(k,j)边替换也是可以的。
所以在floyd中顺便统计下就可以了。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_N 105 5 6 using namespace std; 7 8 int n,t,cas; 9 int dis[MAX_N][MAX_N]; 10 bool vis[MAX_N][MAX_N]; 11 12 void read() 13 { 14 cin>>n; 15 for(int i=1;i<=n;i++) 16 { 17 for(int j=1;j<=n;j++) 18 { 19 cin>>dis[i][j]; 20 } 21 } 22 } 23 24 int floyd() 25 { 26 memset(vis,false,sizeof(vis)); 27 int cnt=n*(n-1); 28 for(int k=1;k<=n;k++) 29 { 30 for(int i=1;i<=n;i++) 31 { 32 for(int j=1;j<=n;j++) 33 { 34 if(i!=j && j!=k && i!=k) 35 { 36 if(dis[i][k]+dis[k][j]<dis[i][j]) return -1; 37 if(dis[i][k]+dis[k][j]==dis[i][j] && !vis[i][j]) 38 { 39 vis[i][j]=true; 40 cnt--; 41 } 42 } 43 } 44 } 45 } 46 return cnt; 47 } 48 49 void work() 50 { 51 int ans=floyd(); 52 cout<<"Case "<<cas<<": "; 53 if(ans==-1) cout<<"impossible"<<endl; 54 else cout<<ans<<endl; 55 } 56 57 int main() 58 { 59 cin>>t; 60 for(cas=1;cas<=t;cas++) 61 { 62 read(); 63 work(); 64 } 65 }