Fight Against Traffic( cf954d )-最短路Dijkstra

训练赛的题目,也是我第一次在比赛里用Dijkstra,先丢题目:
A. Fight Against Traffic
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Little town Nsk consists of n junctions connected by m bidirectional roads. Each road connects two distinct junctions and no two roads connect the same pair of junctions. It is possible to get from any junction to any other junction by these roads. The distance between two junctions is equal to the minimum possible number of roads on a path between them.

In order to improve the transportation system, the city council asks mayor to build one new road. The problem is that the mayor has just bought a wonderful new car and he really enjoys a ride from his home, located near junction s to work located near junction t. Thus, he wants to build a new road in such a way that the distance between these two junctions won't decrease.

You are assigned a task to compute the number of pairs of junctions that are not connected by the road, such that if the new road between these two junctions is built the distance between s and t won't decrease.

Input

The firt line of the input contains integers nms and t (2 ≤ n ≤ 1000, 1 ≤ m ≤ 1000, 1 ≤ s, t ≤ ns ≠ t) — the number of junctions and the number of roads in Nsk, as well as the indices of junctions where mayors home and work are located respectively. The i-th of the following m lines contains two integers ui and vi (1 ≤ ui, vi ≤ nui ≠ vi), meaning that this road connects junctions ui and vi directly. It is guaranteed that there is a path between any two junctions and no two roads connect the same pair of junctions.

Output

Print one integer — the number of pairs of junctions not connected by a direct road, such that building a road between these two junctions won't decrease the distance between junctions s and t.

Examples
input
5 4 1 5
1 2
2 3
3 4
4 5
output
0
input
5 4 3 5
1 2
2 3
3 4
4 5
output
5
input
5 6 1 5
1 2
1 3
1 4
4 5
3 5
2 5
output
3

题目大意是,给出一个无权无向图,问最多能连接其中的多少个节点对且保持节点s,t间的距离不变。

分析:因为直接对每两个节点进行检查不大好处理,我想到一个迂回一点的办法。对起始点分别使用Dijkstra,这样可以储存每个点到s,t的距离,然后再遍历每个点对,判断连接这两个点会不会减少s,t之间的距离,最后从全部点对中去掉这一部分和原先的最短路,得到的就是不影响最短距离的点对数。

至于Dijkstra的具体实现,实际上就是bfs,然后对每一个点检查相邻点的最短长度能否被更新。

大致的复杂度为n^2

下面丢出代码:


#include<iostream> 
#include<vector>//正常应该是用queue,但最近用vector用的比较多,写的时候一不小心用错了,后来发现的时候已经快写完了
#include<algorithm>
#include<stack>
using namespace std;
const int MAX=0x7fffffff;
int map[1005][1005];
struct p{
    int p,shests,shestt;//p是点的序号,shests和shestt分别是到s,t的最短路径
}p[1005];
int min(int a,int b){
    return a<b?a:b;
}
bool cmp(struct p a,struct p b){
    if(a.shests!=b.shests) return a.shests<b.shests;
    return a.shestt<b.shestt;
}
int main(){
    vector<int>jc;
    int i,j,n,m,s,t,u,v,k,x,ans,sum(0);
    cin>>n>>m>>s>>t;
    for(i=0;i<=n;i++) {
    p[i].shests=MAX;    
    p[i].shestt=MAX;
    p[i].p=i;
    }//初始化
    for(i=0;i<m;i++){
        scanf("%d%d",&u,&v);
        map[u][v]=1;
        map[v][u]=1;
    }//读入,用邻接矩阵储存两个点的相连关系
    jc.push_back(s);//Dijkstra
    p[s].shests=0;
    for(x=0,k=1;k!=x;x++){
        i=jc[x];
        for(j=1;j<=n;j++)
            if(map[i][j]&&(p[j].shests>p[i].shests+1)) p[j].shests=p[i].shests+1,jc.push_back(j),k++;
    }
    jc.clear();
    jc.push_back(t);//再一次Dijkstra
    p[t].shestt=0;
    for(x=0,k=1;k!=x;x++){
        i=jc[x];
        for(j=1;j<=n;j++)
            if(map[i][j]&&(p[j].shestt>p[i].shestt+1)) p[j].shestt=p[i].shestt+1,jc.push_back(j),k++;
    }
//    sort(p+1,p+n+1,cmp);
/*    cout<<endl;
    for(i=1;i<=n;i++) cout<<p[i].p<<" "<<p[i].shests<<" "<<p[i].shestt<<endl;
    cout<<endl;*/
    
    ans=p[t].shests;
    
    for(i=1;i<n;i++){
        for(j=i+1;j<=n;j++)//检查每一个点对
            if(!map[p[i].p][p[j].p]&&(p[i].shests+p[j].shestt+1<ans||p[i].shestt+p[j].shests+1<ans)){//        cout<<p[i].p<<" "<<p[j].p<<endl;
                sum++;}}//    cout<<sum<<endl;
    cout<<n*(n-1)/2-m-sum<<endl;return0;}

 

Dijkstra

转载于:https://www.cnblogs.com/wengsy150943/p/10539959.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值