福州大学2271x——弗洛伊德最短路
福州大学 Problem 2271 X
题意
N个城市,M条路,保证最开始是连通图。(N<=100) 现在需要删除掉一些路,要保证删除后各个城市之间的距离不变(最短路径长度不变) 尽可能得使得删除的路的条数更多。 两个城市之间可能有多条路。
思路
我们是要删除一些边,保证城市间最短路长度不变。 首先两个城市间若有1条以上的路,那么必定是要删除。 其次,我么可以用弗洛伊德最短路算法,算得各个城市之间的最短路径长度。然后我们考虑删除,原图中两个城市间有路并且大于两个城市的最短路,那么此边必定要删除。 然后,因为题目是要尽可能删除更多的边,那么当存v1与v2的一条边u,u的长度等于v1与v2的最短路径长度且u!=此最短路,那么u就要被删除,因为要尽可能多删除。
AC代码
#include<stdio.h>
#include<iostream>
#include<cmath>
#include<cstring>
#define inf 0x3f3f3f3f
using namespace std ;
const int maxn = 110 ;
int map [maxn][maxn];
int cost[maxn][maxn];
int vis[maxn][maxn];
int n,m;
void flo()
{
int k,i,j;
for (k=1 ; k<=n; k++)
for (i=1 ; i<=n; i++)
for (j=1 ; j<=n; j++)
{
if (i == j)
continue ;
if (map [i][j]>=map [i][k]+map [k][j] )
{
map [i][j]=map [i][k]+map [k][j];
vis[i][j] = 1 ;
}
}
}
int main()
{
int T;
scanf ("%d" ,&T);
int Case = 1 ;
while (T--)
{
int ans1 = 0 ;
int ans2 = 0 ;
memset (vis,0 ,sizeof (vis));
scanf ("%d%d" ,&n,&m);
for (int i=1 ; i<=n; i++)
for (int j=1 ; j<=n; j++)
cost[i][j]=inf;
for (int i = 0 ; i < m ;i++)
{
int x,y,s;
scanf ("%d%d%d" ,&x,&y,&s);
if (cost[x][y] != 0 && cost[x][y] != inf)
{
ans1 ++;
cost[x][y] = min(cost[x][y],s);
cost[y][x] = min(cost[y][x],s);
}
else
{
cost[x][y] = s;
cost[y][x] = s;
}
}
for (int i = 1 ; i <= n ;i++)
{
for (int j = 1 ; j <= n ;j++)
{
map [i][j] = cost[i][j];
}
}
flo();
for (int i =1 ;i <= n ;i++)
{
for (int j = 1 ; j<= n ;j++)
{
if (cost[i][j] != 0 && cost[i][j] != inf )
{
if (map [i][j] < cost[i][j])
{
ans2++;
}
else if (map [i][j] == cost[i][j] && vis[i][j] == 1 )
{
ans2++;
}
}
}
}
int ans = ans1 + ans2 / 2 ;
printf ("Case %d: %d\n" ,Case++,ans);
}
return 0 ;
}