L. Right Build 【经典的最短路问题,dijkstra+优先队列】

L. Right Build

time limit per test2.0 s
memory limit per test256 MB
inputstandard input
outputstandard output

In a MMORPG «Path of Exile» characters grow by acquiring talents for special talent points received in a game process. Talents can depend on others. A talent can be acquired only if a character has at least one of the talents it depends on. Acquiring one talent costs one talent point. At the beginning of the game a character has a single starting talent.

Schoolboy Vasiliy decided to record a video manual how to level-up a character in a proper way, following which makes defeating other players and NPCs very easy. He numbered all talents as integers from 0 to n, so that the starting talent is numbered as 0. Vasiliy thinks that the only right build is acquiring two different talents a and b as quickly as possible because these talents are imbalanced and much stronger than any others. Vasiliy is lost in thought what minimal number of talent points is sufficient to acquire these talents from the start of the game.

Input

The first line contains four space-separated integers: n, m, a and b (2 ≤ n, m ≤ 2·105, 1 ≤ a, b ≤ n, a ≠ b) — the total number of talents, excluding the starting talent, the number of dependencies between talents, and the numbers of talents that must be acquired.

Each of the next m lines contains two space-separated integers: xj and yj (0 ≤ xj ≤ n, 1 ≤ yj ≤ n, xj ≠ yj), which means the talent yj depends on the talent xj. It’s guaranteed that it’s possible to acquire all talents given the infinite number of talent points.

Output

Output a single integer — the minimal number of talent points sufficient to acquire talents a and b.

Examples

input

6 8 4 6
0 1
0 2
1 2
1 5
2 3
2 4
3 6
5 6

output

4

input

4 6 3 4
0 1
0 2
1 3
2 4
3 4
4 3

output

3

这是盗的mengxiang000000的题,的确很经典的题,推荐大家做下
题意:给你n+1个点,m条边,然后给你两个点a,b,求从0点到a,b点长度的总和。
分析:一眼看到这题就知道就最短路,但是无从下手,看了大牛的分析才懂的,就是先正向求出从0点的单源最短路,然后再反向建图,依次求出从a,b出发的单源最短路,最后再枚举一个中转点,记做c,即答案为:dis[0->c] + dis[c->a]+dis[c->b] 遍历一遍求出个min即可

吐槽: 这个题真难找啊,还好是在vj上找的

参考代码

#include
using namespace std;

const int N = 2e5 + 10, INF = 0x3f3f3f3f;
vector<int> e[N];
int n,m,a,b;
int aa[N],bb[N]; //反向建图时使用
int dis[3][N]; //一个是dis[0],dis[a],dis[b],分开也可以,这里无所谓

void init(){for(int i = 0;i <= n;i++)e[i].clear();}
void dij(int id,int s){ //优先队列优化
    for(int i = 0;i <= n;i++) dis[id][i] = INF;
    dis[id][s] = 0;
    priority_queueint,int> > q;
    q.push(make_pair(0,s));
    while(!q.empty()){
        int u = q.top().second;
        q.pop();
        for(int i = 0;i < e[u].size();i++){
            int v = e[u][i];
            if(dis[id][v] > dis[id][u] + 1){
                dis[id][v] = dis[id][u] + 1;
                q.push(make_pair(-dis[id][v],v));
            }
        }
    }
}
int main(){
    ios_base::sync_with_stdio(0);
    cin>>n>>m>>a>>b;
    init();
    for(int i = 0;i < m;i++){
        int x,y;cin>>x>>y;
        aa[i] = x;bb[i] = y;
        e[x].push_back(y);
    }
    dij(0,0);
    init();
    for(int i = 0;i < m;i++) e[bb[i]].push_back(aa[i]);//反向建图
    dij(1,a);
    dij(2,b);
    int ans = 2000000000;
    for(int i = 0;i <= n;i++)
        ans = min(ans,dis[0][i]+dis[1][i]+dis[2][i]);
    cout<return 0;
}
  • 如有错误或遗漏,请私聊下UP,ths

你可能感兴趣的:(最短路)