1. 程式人生 > >cf- Educational Codeforces Round 40 -D

cf- Educational Codeforces Round 40 -D

efi code 短路徑 emp brush log urn end cpp

題意:給你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;
}

  

---恢復內容結束---

cf- Educational Codeforces Round 40 -D