zoukankan      html  css  js  c++  java
  • UVA

    题意:求无向图去掉每一条边后的两两最短路之和

    非标解

    之前见过去掉每个点的两两最短路的问题,用的区间分治+Floyed,我想着边的也可以试一试,结果就过了。。。

    设g(l,r)表示除了[l,r]区间内的边都加上了的情况下的两两最短路矩阵,那么有递推式$left{egin{matrix}egin{aligned}&g(l,mid)=cal(g(l,r),mid+1,r)\&g(mid+1,r)=cal(g(l,r),l,mid)end{aligned}end{matrix} ight.$,cal(g,l,r)表示将在g矩阵的基础上把[l,r]区间的边加进去后得到的新的最短路矩阵,加边过程仿照Floyed算法有更新公式$g[i][j]=min(g[i][j],g[i][u]+cost(u,v)+g[v][j],g[i][v]+cost(v,u)+g[u][j])$,终止条件为l=r,分治求解即可(其实比起分治我觉得更像是在线段树上dfs)

    复杂度$O(n^2mlogm)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 typedef double db;
     5 const int N=100+10,inf=0x3f3f3f3f;
     6 #define mid ((l+r)>>1)
     7 int g[20][N][N],ans,ans2,L,n,m;
     8 struct E {int u,v,c;} e[1010];
     9 void cal(int d,int l,int r) {
    10     memcpy(g[d],g[d-1],sizeof g[d]);
    11     for(int t=l; t<=r; ++t) {
    12         int u=e[t].u,v=e[t].v,c=e[t].c;
    13         for(int i=1; i<=n; ++i)
    14             for(int j=1; j<=n; ++j)
    15                 g[d][i][j]=min(g[d][i][j],min(g[d][i][u]+c+g[d][v][j],g[d][i][v]+c+g[d][u][j]));
    16     }
    17 }
    18 void solve(int d=0,int l=1,int r=m) {
    19     if(l==r) {
    20         int c=0;
    21         for(int i=1; i<=n; ++i)
    22             for(int j=1; j<=n; ++j)c+=g[d][i][j];
    23         ans=max(ans,c);
    24         return;
    25     }
    26     cal(d+1,l,mid),solve(d+1,mid+1,r);
    27     cal(d+1,mid+1,r),solve(d+1,l,mid);
    28 }
    29 
    30 int main() {
    31     while(~scanf("%d%d%d",&n,&m,&L)) {
    32         ans=ans2=0;
    33         for(int i=1; i<=n; ++i)
    34             for(int j=1; j<=n; ++j)
    35                 g[0][i][j]=(i==j)?0:L;
    36         for(int i=1; i<=m; ++i)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].c);
    37         solve();
    38         for(int t=1; t<=m; ++t) {
    39             int u=e[t].u,v=e[t].v,c=e[t].c;
    40             for(int i=1; i<=n; ++i)
    41                 for(int j=1; j<=n; ++j)
    42                     g[0][i][j]=min(g[0][i][j],min(g[0][i][u]+c+g[0][v][j],g[0][i][v]+c+g[0][u][j]));
    43         }
    44         for(int i=1; i<=n; ++i)for(int j=1; j<=n; ++j)ans2+=g[0][i][j];
    45         printf("%d %d
    ",ans2,ans);
    46     }
    47     return 0;
    48 }
  • 相关阅读:
    [leetCode]剑指 Offer 43. 1~n整数中1出现的次数
    [leetCode]剑指 Offer 42. 连续子数组的最大和
    HDU
    HDU
    HDU
    HDU
    HDU
    HDU
    POJ
    POJ
  • 原文地址:https://www.cnblogs.com/asdfsag/p/14615100.html
Copyright © 2011-2022 走看看