1. 程式人生 > >洛谷——P3906 Geodetic集合

洛谷——P3906 Geodetic集合

sca front mem truct cto orange 整數 1-n push_back

P3906 Geodetic集合

題目描述

圖G是一個無向連通圖,沒有自環,並且兩點之間至多只有一條邊。我們定義頂點v,u最短路徑就是從v到u經過邊最少的路徑。所有包含在v-u的最短路徑上的頂點被稱為v-u的Geodetic頂點,這些頂點的集合記作I(v, u)。

我們稱集合I(v, u)為一個Geodetic集合。

例如下圖中,I(2, 5)={2, 3, 4, 5},I(1, 5)={1, 3, 5},I(2, 4)={2, 4}。

技術分享圖片

給定一個圖G和若幹點對v,u,請你分別求出I(v, u)。

輸入輸出格式

輸入格式:

輸入文件geo.in,第一行為兩個整數n,m,分別表示圖G的頂點數和邊數(頂點編號1-n,n≤40)。下接m行,每行兩個整數a,b表示頂點a和b之間有一條無向邊。

第m+2行有一個整數k,表示給定的點對數。下接k行,每行兩個整數v,u。。

輸出格式:

輸出文件geo.out,共k行,每行對應輸入文件中每一個點對v,u,按頂點編號升序輸出I(v, u)。同一行的每個數之間用空格分隔。

輸入輸出樣例

輸入樣例#1: 復制
5 6
1 2
1 3
2 3
2 4
3 5
4 5
3
2 5
5 1
2 4
輸出樣例#1: 復制
2 3 4 5
1 3 5
2 4

解題報告:

題目大意:給你一個無向連通圖,詢問兩點之間最短路徑上的點

spfa 跑最短路,記錄到達每個節點最短路徑上的的前驅即可,不過前驅可能有好幾個,vector<int>G[N]存儲即可

此題有個坑點,一定要去重!!!

#include<bits/stdc++.h>

#define N 101001
using namespace std;

int n,m,head[N],tot;
bool pvis[N];
struct nod {
    int to,next;
} e[N];
void add(int u,int v) {
    e[++tot].to=v,e[tot].next=head[u],head[u]=tot;
}

int q,d[N];
bool vis[N];
queue<int>Q;
vector
<int>G[50]; void spfa(int x) { while(!Q.empty()) Q.pop(); Q.push(x); for(int i=1; i<=n; i++) G[i].clear(); memset(vis,0,sizeof(vis)); memset(d,0x3f,sizeof(d)); vis[x]=1,d[x]=0; while(!Q.empty()) { int u=Q.front(); Q.pop(); vis[u]=0; for(int i=head[u]; i; i=e[i].next) { int v=e[i].to; if(d[v]>d[u]+1) { d[v]=d[u]+1; if(!vis[v]) { G[v].clear(); G[v].push_back(u); Q.push(v); vis[v]=1; } } else if(d[v]==d[u]+1) { G[v].push_back(u); } } } } int an[N],tpt; void dg(int u,int a) { int sz=G[u].size(); an[++tpt]=u; for(int i=0; i<sz; i++) { int v=G[u][i]; if(v==a) continue; dg(v,a); } } int main() { scanf("%d%d",&n,&m); for(int a,b,i=1; i<=m; i++) { scanf("%d%d",&a,&b); add(a,b),add(b,a); } scanf("%d",&q); for(int a,b,i=1; i<=q; i++) { scanf("%d%d",&a,&b); // memset(pvis,0,sizeof(pvis)); spfa(a); memset(an,0,sizeof(an)); tpt=0; dg(b,a); an[++tpt]=a; sort(an+1,an+1+tpt); for(int j=1; j<=tpt; j++){ if(an[j]!=an[j+1]) printf("%d ",an[j]); } puts(""); } return 0; }

洛谷——P3906 Geodetic集合