h3mky0's blog

主に競プロについて書きます

AOJ2608 Minus One

問題概要
無向グラフGについて2点s, tの最短経路をd_{\min }としたとき、 e = \left( u,v\right) (ただし, u\not=v )を満たす辺を追加したときのs, t間の最短経路がd_{\min }-1となるような辺はいくつ存在するか。
各辺の重みは1とする。

考えたこと
いま e = \left( u,v\right)を考えた時, d_{s,u} + d_{u,v} + d_{v,t} = d_{\min }-1 を満たせばよい。
すなわち,  d_{v,t} = d_{\min }-1 - d_{s,u} - d_{u,v}を考えればよく, これは頂点s, tについて各点の最短経路を求め, sからの距離を固定して条件を満たす辺を全探索すればよい。
計算量はO(n)

ACコード

#include <bits/stdc++.h>
using namespace std;
#define FOR(i,s,n) for(int i=s;i<(int)n;++i)
#define REP(i,n) FOR(i,0,n)
 
typedef long long ll;
vector<vector<int>> g(100010);
int ds[100010];
int dg[100010];
int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(12);
    
    
    int N, M, s, t; cin >> N >> M >> s >> t;

    s--; t--;

    REP(i,M){
        int x, y; cin >> x >> y;
        x--; y--;
        g[x].push_back(y);
        g[y].push_back(x);
    }

    REP(i,N) ds[i] = dg[i] = INT_MAX;

    {
        queue<int> q;
        q.push(s);
        ds[s] = 0;
        while(q.size()){
            int v = q.front();
            q.pop();

            for(int i=0; i<g[v].size(); i++){
                if(ds[g[v][i]] == INT_MAX){
                    ds[g[v][i]] = ds[v] + 1;
                    q.push(g[v][i]);
                }
            }
        }
    }

    
    {
        queue<int> q;
        q.push(t);
        dg[t] = 0;
        while(q.size()){
            int v = q.front();
            q.pop();

            for(int i=0; i<g[v].size(); i++){
                if(dg[g[v][i]] == INT_MAX){
                    dg[g[v][i]] = dg[v] + 1;
                    q.push(g[v][i]);
                }
            }
        }
    }

    map<ll, ll> mp, mp2;
    REP(i,N){
        mp[ds[i]]++;
        mp2[dg[i]]++;
    }

    int e = ds[t]-2;
    ll ans = 0;
    for(int i=0; i<=e; i++){
        int v = e-i;
        
        ans += mp[i] * mp2[v];
    }
    cout << ans << endl;
    return 0;
}

使ったサイト
入力した数式をtex形式に変換してくれる
webdemo.myscript.com