最短倍増| Luogu P2886 [USACO07NOV]牛は牛のリレーを中継します

トピックリンク

問題の意味:最短辺を介してS N Eを見つける無向連結グラフを、与えられました。

データ範囲:エッジ数\(\ル100 \) 頂点IDの\(\ le1000 \) \(\タイムズのN \ LE1 6〜10 ^ \)

ソリューション:

3つの最短溶液があり、そのようなデータは、範囲を使用することができる\(フロイド\)を

ことができる([I]、[J fを\ ] [K] \) を表し\(Iは\)する(J \)を\\(K \)最短エッジ、明らかTLEを

考えてみて倍増しました。前処理\(= 2 ^ K \ K)、この時間([I] [J F \分\ {[I] [L] [K-1] + F F [L] [J] =] [K] [K-1] \} \ )

\(\ N-)バイナリ分割、明らかに最初の\(X \)ビット\(1 \) 直接発呼\(F [] [] [X] \)

ほぼ同様の方法で続くによって決定することができる\(K \)エッジの最短。

頂点の実行に応じて、なお\(フロイド\)時間外、それは離散する必要があります。

コード

#include<bits/stdc++.h>
#define s(S) 1-S%2
#define g(S) S%2
using namespace std;
const int oo=1000000000;
int n,t,s,e,u,v,c,maxp;
int f[1010][1010][20],ans[1010][1010][2],num[1010],snum;
int main()
{
    cin>>n>>t>>s>>e;
    num[s]=1;num[e]=2;snum=2;s=1;e=2;
    for (int i=1;i<=t;i++)
    {
        cin>>c>>u>>v;
        if (num[u]) u=num[u];else num[u]=++snum,u=num[u];
        if (num[v]) v=num[v];else num[v]=++snum,v=num[v];
        f[u][v][0]=f[v][u][0]=c;
        maxp=max(maxp,max(u,v));
    }   
    for (int k=0;(1<<k)<=n;k++)
    for (int i=1;i<=maxp;i++)
      for (int j=1;j<=maxp;j++)
      {
        if (k!=0||((!f[i][j][k]))) f[i][j][k]=oo;
      }
     for (int k=1;(1<<k)<=n;k++)
      for (int l=1;l<=maxp;l++)
        for (int i=1;i<=maxp;i++)
          for (int j=1;j<=maxp;j++)
          {
              f[i][j][k]=min(f[i][j][k],f[i][l][k-1]+f[l][j][k-1]);
          }//预处理
    int S=0,sum=1,S1=0;
    while (n&&!(n&1))
    {
        n>>=1;S1++;
    }
    for (int i=1;i<=maxp;i++)
        for (int j=1;j<=maxp;j++)
        {
            ans[i][j][S]=f[i][j][S1];
        }
    n>>=1;S1++;
    while (n&&!(n&1))
    {
        n>>=1;S1++;
    }
    for (int i=1;i<=maxp;i++)
        for (int j=1;j<=maxp;j++)
        {
            ans[i][j][1]=oo;
        }
    while (n)
    {
        S++;S%=2;
        for (int l=1;l<=maxp;l++)
        for (int i=1;i<=maxp;i++)
        for (int j=1;j<=maxp;j++)
        {
            ans[i][j][S]=min(ans[i][j][S],ans[i][l][s(S)]+f[l][j][S1]);
        }
        n>>=1;S1++;
        while (n&&!(n&1))
        {
            n>>=1;S1++;
        }
        for (int i=1;i<=maxp;i++)
        for (int j=1;j<=maxp;j++)
        {
            ans[i][j][s(S)]=oo;
        }
    }//求ans,与上面几乎一致
    cout<<ans[s][e][S]<<endl;
    return 0;
}

おすすめ

転載: www.cnblogs.com/fmj123/p/Luogu2886.html