洛谷——P3906 Geodetic集合
阿新 • • 發佈:2018-08-28
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集合