这是一个最短路树的题目 ,
这里有一个陷阱 , 有重边 , 如果有重边时必须用第二短的边来代替 。
解法:我们求出一个源点出发的最短路之后 , 我们得到的是一颗树 , 但是这颗树不一定是最小生成树 , 因此如果我们要删除的边在这颗树上 , 那么这个源点出发的最短路径长度就会改变 , 如果不在 , 那么就肯定不会改变,因此我们就只需要判断这条边是否存在这棵树上。
写代码时 , 一定要头脑清醒 , 不能出一点差错 , 不然 , 到后面来找时 , 很难找到
#include
#include
#include
#include
#include
#include
using namespace std;
const int MAXN = 110;
const long long INF = 100000000000000 ;
vectorgrap[MAXN];
long long g[MAXN][MAXN] , g1[MAXN][MAXN];
int n , m , p[MAXN][MAXN] , l = 0;
long long sum1 = 0 , d[MAXN][MAXN];
void init()
{
for(int i = 1 ; i <= n; i++)
grap[i].clear();
memset(g , 0 , sizeof(g));
memset(g1 , 0 , sizeof(g1));
memset(p , 0 , sizeof(p));
sum1 = 0;
}
long long spfa(int s) // 初始化求所有最短路的和
{
int i , done[MAXN] ;
memset(done , 0 , sizeof(done));
for(i = 1; i <= n; i++)
d[s][i] = INF ;
d[s][s] = 0;
queueq ;
q.push(s);
//
队列记录下点
while(!q.empty())
{
int u = q.front() ; q.pop() ;
done[u] = 0;
for(i = 0 ; i < grap[u].size() ; i++)
{
int v = grap[u][i];
if(d[s][v] > (d[s][u] + g[u][v]))
{
d[s][v] = d[s][u] + g[u][v];
p[s][v] = u;
if(!done[v]) { q.push(v) ;
done[v] = 1; }
}
}
}
long long sum = 0;
for(i = 1; i <= n; i++)
{
if(d[s][i] >= INF)
//
如果有某个点是孤立点
sum += l;
else sum += d[s][i] ;
}
return sum;
}
long long spfa1(int s) // 初始化求所有最短路的和
{
int i , done[MAXN] ;
long long d1[MAXN] , sum = 0 ;
memset(done , 0 , sizeof(done));
for(i = 1; i <= n; i++)
d1[i] = INF ;
d1[s] = 0;
queueq ;
q.push(s);
//
队列记录下点
while(!q.empty())
{
int u = q.front() ; q.pop() ;
done[u] = 0;
for(i = 0 ; i < grap[u].size() ; i++)
{
int v = grap[u][i];
if(g[u][v] && d1[v] > (d1[u] + g[u][v]))
{
d1[v] = d1[u] + g[u][v];
if(!done[v]) { q.push(v) ;
done[v] = 1; }
}
}
}
for(i = 1; i <= n; i++)
{
if(d1[i] >= INF)
//
如果有某个点是孤立点 , 那么就直接返回
sum += l;
else sum += d1[i] ;
}
return sum;
}
int main()
{
while(scanf("%d %d %d" , &n , &m , &l) != EOF)
{
init();
int i , j , k , b , x , y;
long long
dist ;
for(i = 0 ; i < m ; i++)
{
cin>>x>>y>>dist;
if(g[x][y])
{
if(g[x][y] > dist)
{
g1[x][y] = g1[y][x] = g[x][y] ;
g[x][y] = dist;
g[y][x] = dist;
}
else if(g1[x][y] == 0 || g1[x][y] > dist)
g1[x][y] = g1[y][x] = dist;
}
else
{
grap[x].push_back(y);
grap[y].push_back(x);
g[x][y] = dist;
g[y][x] = dist;
}
}
long long d_sum[MAXN] ;
for(i = 1; i <= n; i++)
{
d_sum[i] = spfa(i);
sum1 += d_sum[i];
}
long long max_sum
, sum2 = 0;
for(i = 1; i <= n
; i++)
for(j = i+1 ; j <= n; j++)
{
max_sum = sum1 ;// 在这个地方 , wa了很多次 , max_sum的赋值必须放在if的外面。
if(g[i][j])
{
dist = g[i][j];
if(g1[i][j])
g[i][j] = g[j][i] = g1[i][j] ;
else
g[i][j] = g[j][i] = 0;
for(k = 1; k <= n; k++)
{
for(b = 1; b <= n; b++)
if((p[k][b] == i && b ==j) || (p[k][b] == j && b == i))
break;
if(b <= n)
{
max_sum -= d_sum[k];
max_sum += (long long)spfa1(k);
}
}
g[i][j] = g[j][i] = dist;
}
//cout<<max_sum<<endl;
if(max_sum > sum2)
{
sum2 = max_sum;
}
}
cout<<sum1<<" "<<sum2<<endl;
}
return 0;
}
解法:我们求出一个源点出发的最短路之后 , 我们得到的是一颗树 , 但是这颗树不一定是最小生成树 , 因此如果我们要删除的边在这颗树上 , 那么这个源点出发的最短路径长度就会改变 , 如果不在 , 那么就肯定不会改变,因此我们就只需要判断这条边是否存在这棵树上。
写代码时 , 一定要头脑清醒 , 不能出一点差错 , 不然 , 到后面来找时 , 很难找到
#include
#include
#include
#include
#include
#include
using namespace std;
const int MAXN = 110;
const long long INF = 100000000000000 ;
vectorgrap[MAXN];
long long g[MAXN][MAXN] , g1[MAXN][MAXN];
int n , m , p[MAXN][MAXN] , l = 0;
long long sum1 = 0 , d[MAXN][MAXN];
void init()
{
}
long long spfa(int s)
{
}
long long spfa1(int s)
{
}
int main()
{
}