LA 4080 Warfare A…

来源:互联网 发布:linux解析文件 编辑:程序博客网 时间:2024/06/03 05:50
这是一个最短路树的题目 ,  这里有一个陷阱 , 有重边 , 如果有重边时必须用第二短的边来代替。

解法:我们求出一个源点出发的最短路之后 , 我们得到的是一颗树 , 但是这颗树不一定是最小生成树 , 因此如果我们要删除的边在这颗树上, 那么这个源点出发的最短路径长度就会改变 , 如果不在 ,那么就肯定不会改变,因此我们就只需要判断这条边是否存在这棵树上。

写代码时 , 一定要头脑清醒 , 不能出一点差错 , 不然 , 到后面来找时 , 很难找到
#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 longsum = 0;
    for(i = 1; i<= n; i++)
    {
       if(d[s][i]>= INF)  // 如果有某个点是孤立点
          sum +=l;
       else sum +=d[s][i] ;


    }
    returnsum;
}

long long spfa1(int s)  // 初始化求所有最短路的和
{
    int i ,done[MAXN] ;
    long longd1[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] ;


    }
    returnsum;
}

int main()
{
   while(scanf("%d %d %d" , &n , &m ,&l) != EOF)
    {
      init();
       int i , j ,k , b , x , y;
       longlong  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;
             }
             elseif(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 longd_sum[MAXN] ;
       for(i = 1; i<= n; i++)
       {
          d_sum[i] =spfa(i);
          sum1 +=d_sum[i];
       }

       long longmax_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;

    }
    return0;
}


0 0
原创粉丝点击