大致题意:
zznuoj,大致题意:从A点出发达到B点去解救人质,再从B点返回到A点,经历第二遍的点只计算一次即可,AB两点不计数!求完成任务最少需要经过的点数。 大致思路:暴力!从起点到终点,和从终点到起点这两趟路其实恰好可以分开,互不影响地进行取并集计算找最佳值! BFS枚举前1000条从起点A到终点B的路径(仅统计每种搜索的经过的点数)进set1,然后反之再搜索一次再统计一遍存进set2!然后两两求出交集后取并集最小的哪一个就是结果。 当然BFS时要舍远求近,仅保留前1000个最短的路径,两次bfs其实步骤一样——对调起点和终点即可! 优化:set<int>mp1[N]; //可替换成bool,再开一个bool数组再进行比较。
题解:
1 #include<stdio.h> 2 #include<string.h> 3 #include<math.h> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 #include<set> 8 using namespace std; 9 #define inf 0x3f3f3f3f 10 #define N 108 11 #define ll long long 12 #define mem(a,x) memset(a,x,sizeof(a)) ///peace keeper 13 14 set<int>mp1[N]; //可替换成bool,再开一个bool数组再进行比较 15 set<int>mp2[N]; 16 17 vector<int>a[N]; 18 19 int n,m,A,B; 20 int val[N]; 21 bool vis[N]; 22 struct node{ 23 int x,step; //x表示当前的走到的那个的点,step表示抵达当前点走过的步数。 24 bool vis[N]; //统计抵达当前点x的所有点 25 bool operator< (const node &p)const{ 26 return p.step<step;///step小的先出去 27 }; 28 }; 29 void debug(bool y[],int n){ 30 for(int i=1;i<=n;i++) 31 printf(" %d",y[i]); 32 cout<<endl; 33 } 34 int bfs1(int A,int B,int n){ 35 queue<node>Q; 36 node st,next,now; 37 st.x=A;st.step=0;mem(st.vis,0);st.vis[A]=1; 38 Q.push(st); 39 int cnt=0; 40 41 while(Q.size()>0){ 42 now=Q.front(); 43 Q.pop(); 44 if(cnt>=100)break ; 45 for(int i=0;i<(int)a[now.x].size();i++){ 46 int v=a[now.x][i]; 47 // printf("%d->%d ",now.x,v); 48 if(!now.vis[v]) 49 { 50 next=now; 51 next.vis[v]=1; 52 53 next.x=v;next.step=now.step+1; 54 /// debug(next.vis,n); 55 if(v==B){ 56 cnt++; 57 mp1[cnt].clear(); 58 for(int j=1;j<=n;j++) 59 { 60 if(next.vis[j])mp1[cnt].insert(j); 61 } 62 continue; 63 } 64 65 Q.push(next); 66 } 67 } 68 } 69 return cnt; 70 } 71 int bfs2(int A,int B,int n){ //反向搜索一波,找寻N条最短路 72 queue<node>Q; 73 node st,next,now; 74 st.x=B;st.step=0;mem(st.vis,0);st.vis[B]=1; 75 Q.push(st); 76 int cnt=0; 77 78 while(Q.size()>0){ 79 now=Q.front(); 80 Q.pop(); 81 if(cnt>=100)break ; 82 for(int i=0;i<(int)a[now.x].size();i++){ 83 int v=a[now.x][i]; 84 // printf("%d->%d ",now.x,v); 85 if(!now.vis[v]) 86 { 87 next=now; 88 next.vis[v]=1; 89 next.x=v;next.step=now.step+1; 90 if(v==A){ 91 cnt++; 92 mp2[cnt].clear(); 93 for(int j=1;j<=n;j++) 94 { 95 if(next.vis[j])mp2[cnt].insert(j); 96 } 97 continue; 98 } 99 Q.push(next); 100 } 101 } 102 } 103 return cnt; 104 } 105 106 int solve(int cnt1,int cnt2){ 107 108 109 int ans=inf; 110 for(int i=1;i<=cnt1;i++){ 111 for(int j=1;j<=cnt2;j++){ 112 set<int>mp; 113 set<int>::iterator it; 114 for(it=mp1[i].begin();it!=mp1[i].end();++it){ 115 mp.insert(*it); 116 // printf("[%d] ",*it); 117 } 118 // cout<<" *** "; 119 for(it=mp2[j].begin();it!=mp2[j].end();++it){ 120 mp.insert(*it); 121 // printf("(%d) ",*it); 122 } 123 ans=min(ans,(int)mp.size()); 124 // cout<<endl; 125 } 126 } 127 return ans-2; 128 } 129 130 int main(){ 131 132 int T; 133 cin>>T; 134 while(T--){ 135 scanf("%d%d%d%d",&n,&m,&A,&B); 136 int xi,yi; 137 // memset(val,inf,sizeof(val)); 138 for(int i=1;i<=n;i++) 139 a[i].clear(); 140 141 for(int i=1;i<=m;i++) 142 { 143 scanf("%d %d",&xi,&yi); 144 a[xi].push_back(yi); 145 } 146 if(A==B){ 147 printf("0 ");continue; 148 } 149 int cnt1=bfs1(A,B,n); 150 int cnt2=bfs2(A,B,n); 151 152 printf("%d ",solve(cnt1,cnt2)); 153 } 154 155 return 0; 156 }