题意:给你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; }
---恢复内容结束---