Official

F - Make Bipartite Editorial by sugarrr


頂点 \(0,1,\ldots,N\) の順に頂点を赤青に塗り分けて、同色の頂点を結ぶ辺の重みを足すことを考えましょう。

頂点 \(0\) は赤色として一般性を失いません。

ここで、一旦頂点 \(1\) と頂点 \(N\) を結ぶ辺のみ無視したうえで、次の \(dp\) を考えます。

\(dp[i][j][k] :=\) 頂点 \(i\) まで色を塗り終わった時の辺の重みの和の最小値

ただし、頂点 \(i\) の色は \(j\) で、頂点 \(1\) の色は \(k\) である。( \(j\)\(k\) は、\(0\) を赤色、\(1\) を青色とする)

\(dp[i]\)\(dp[i-1]\) から求めることができます。(遷移や初期値が分からなければ下の実装例も参考にしてください。)

最後に、\(dp[N]\) の値に、頂点 \(1\) と頂点 \(N\) を結ぶ辺も考慮すれば答えを出すことができます。

計算量は \(O(N)\) です。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,l,r) for(ll i=l;i<=r;i++)
void chmin(ll &a,ll b){a = min(a,b);}
ll inf = 1e18;

signed main(){
    ll n;cin>>n;
    vector<ll> a(n+1),b(n+1);
    rep(i,1,n)cin>>a[i];
    rep(i,1,n)cin>>b[i];
    vector<vector<vector<ll>>> dp(n+1,vector<vector<ll>>(2,vector<ll>(2,inf)));
    dp[1][0][0] = a[1];
    dp[1][1][1] = 0;
    rep(i,2,n)rep(j,0,1)rep(k,0,1)rep(prej,0,1){
        chmin(dp[i][j][k],dp[i-1][prej][k] + (j==0?a[i]:0) + (j==prej?b[i-1]:0));
    }
    ll ans = inf;
    rep(j,0,1)rep(k,0,1)chmin(ans,dp[n][j][k] + (j==k?b[n]:0));
    cout<<ans<<endl;
    return 0;
}

posted:
last update: