cf- Educational Codeforces Round 40 -D

题意:给你n个点,m条边,一个起点s,一个终点t的无向图,问在某两个点之间加一条边,不改变s到t的最短路径的值的加法有多少种,所有点一定连接;

思路:首先,默认相邻两点的权值都为1,会改变值的情况有:

从s出发,算出s的单源最短路dist,如果dist[x]+1<dist[t];

从t出发,算出t的单源最短路Dist,如果Dist[x]+1<Dist[s];

介于两点之间,s—t之间的某两个点之间+1<dist[s],也就是:dist[x]+Dist[y]+1<(Dist[s] | | dist[t]);

所以从s跑一遍,再从t跑一遍最短路,然后遍历所有点,把能改变值的情况算出来;

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<set>
#include<cmath>
#define maxn 100005
const int inf=99999;
using namespace std;
struct Edge
{
    int next;
    int to;
    int w;
}edge[maxn];
struct node
{
    int num;
    int dist;
    node(int _num=0,int _dist=0):num(_num),dist(_dist){}
    friend bool operator<(node a,node b)
    {
        return a.dist>b.dist;
    }
};
int head[maxn];
int s[maxn];
int n,m,cnt;
int dis[maxn];
int dise[maxn];
int disb[maxn];
int book[1005][1005];
//int book[maxn];
bool vis[maxn];
int be,en;
void add(int u,int v,int w)
{
    edge[cnt].next=head[u];
    edge[cnt].to=v;
    edge[cnt].w=w;
    head[u]=cnt++;
}
void dij(int x)
{
    priority_queue<node>que;
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[x]=0;
    que.push(node(x,0));
    while(!que.empty())
    {
        node p=que.top();
        que.pop();
        int now=p.num;
        if(vis[now])
            continue;
        vis[now]=true;
        for(int i=head[now];i!=-1;i=edge[i].next)
        {
            Edge e=edge[i];
            if(dis[e.to]>dis[now]+e.w&&!vis[e.to])
            {
                dis[e.to]=dis[now]+e.w;
                que.push(node(e.to,dis[e.to]));
            }
        }
    }
}
int main()
{
    int x,y,w;
    cin>>n>>m>>be>>en;
        cnt=0;
        memset(book,0,sizeof(book));
        memset(head,-1,sizeof(head));
        for(int i=1;i<=m;i++)
        {
            cin>>x>>y;
            add(x,y,1);
            add(y,x,1);
        }
        int zz=0;
        int ans=0;
        for(int i=1;i<=n-1;i++)
            zz+=i;
        dij(en);
        for(int i=1;i<=n;i++)
            dise[i]=dis[i];
        dij(be);
        for(int i=1;i<=n;i++)
            disb[i]=dis[i];
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                    continue;
                if(disb[i]+dise[j]+1<dise[be])
                {
                    if(book[i][j]==0&&book[j][i]==0)
                    {
                        ans++;
                    }
                    book[i][j]=book[j][i]=1;
                }
                else if(disb[j]+1<dise[be]-1)
                {
                    if(book[j][en]==0&&book[en][j]==0)
                        ans++;
                    book[j][en]=book[en][j]=1;
                }
                else if(dise[j]+1<disb[en])
                {
                    if(book[be][j]==0&&book[j][en]==0)
                        ans++;
                    book[j][be]=book[be][j]=1;
                }
            }
        }
       // cout<<ans<<endl;
        zz-=m;
        cout<<zz-ans<<endl;
    return 0;
}

  

---恢复内容结束---

posted @ 2018-03-22 21:04  荒岛的龟  阅读(115)  评论(0编辑  收藏  举报