这里有一篇很棒的博客: http://blog.csdn.net/llzhh/article/details/52516591
谈谈学到的东西:
1,set维护东西真的好用,比如维护还能更新的点
2,关于set的删除 st.erase(iter)
最后还要补充一下map和set的一点知识,就是如果你用erase删除一个数字的时候,其实map和set封装了红黑树在里面,说白了就是个链表,但是网上好像是他们所用的空间是固定的,所以比一般的平衡树效率要高,因为申请空间没那么费劲。那我们从树的角度出发,就是链表一样,那么如果你删除了链表中一个节点,此时,再让iter++寻找下一个节点,他是找不到的,因为那个节点已经被删除了,原本节点空间里面的东西全都是随机生成的数字了,找下一个节点的时候都不知道飞到天上去了,那么就会报错。
比如这样
1 for(iter = Set.begin(); iter != Set.end(); iter++) 2 { 3 if(!mark[*iter]) 4 { 5 dist[*iter] = dist[now] + 1; 6 q.push(*iter); 7 Set.erase(iter); 8 } 9 }
这样的写法是错误的,因为先删除节点,后++,此时++指向的就不是下一个节点了,所以我们要在删除前就++,来指向下一个节点。也就是我写的程序那样
1 for(iter = Set.begin(); iter != Set.end(); ) 2 { 3 if(!mark[*iter]) 4 { 5 dist[*iter] = dist[now] + 1; 6 q.push(*iter); 7 Set.erase(iter++); 8 } 9 else 10 iter++; 11 }
这样就可以不报错且正确了,完。
3,另外感觉,set按定位器删除比按值删除要快
4,一个剪枝,if(st.empty())break;
5,不好操作时,我们可以把将要删除的东西放在一个队列里,等遍历完后再进行按值删除.
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 #include<set> 5 using namespace std; 6 const int MAXV=5e5+7,MAXE=5e5+7; 7 int V,E; 8 struct edge{ 9 int next,v; 10 }es[MAXE*2]; 11 int tot,head[MAXV]; 12 void init(){ 13 tot=0; 14 memset(head,-1,sizeof(head)); 15 } 16 void addEdge(int u,int v){ 17 es[tot].v=v; 18 es[tot].next=head[u]; 19 head[u]=tot++; 20 } 21 int d[MAXV]; 22 struct node{ 23 int u,step; 24 }s; 25 int mp[MAXV]; 26 queue<node>q; 27 set<int>st; 28 void bfs(int S){ 29 while(!q.empty())q.pop(); 30 st.clear(); 31 32 for(int i=1;i<=V;++i)if(i!=S)st.insert(i); 33 s.u=S; 34 s.step=0; 35 d[S]=0; 36 q.push(s); 37 38 while(!q.empty()){ 39 node no=q.front();q.pop(); 40 int u=no.u; 41 // printf("u=%d ",u); 42 for(int i=head[u];~i;i=es[i].next){ 43 int v=es[i].v; 44 mp[v]=1; 45 } 46 47 for(auto i=st.begin();i!=st.end();){ 48 if(!mp[*i]){ 49 if(d[*i]!=-1)continue; 50 node ne; 51 ne.step=no.step+1; 52 ne.u=*i; 53 d[*i]=ne.step; 54 q.push(ne); 55 st.erase(i++); 56 }else mp[*i]=0,i++; 57 } 58 if(st.empty())break; 59 } 60 } 61 int main(){ 62 int T;scanf("%d",&T); 63 while(T--){ 64 scanf("%d%d",&V,&E); 65 init(); 66 for(int i=0;i<E;++i){ 67 int a,b;scanf("%d%d",&a,&b); 68 addEdge(a,b); 69 addEdge(b,a); 70 } 71 int S;scanf("%d",&S); 72 memset(d,-1,sizeof(d)); 73 memset(mp,0,sizeof(mp)); 74 bfs(S); 75 bool flag=true; 76 for(int i=1;i<=V;++i){ 77 if(d[i]!=0){ 78 printf(flag?"%d":" %d",d[i]); 79 flag=false; 80 } 81 } 82 printf(" "); 83 } 84 return 0; 85 }