這裏有一篇很棒的博客: http://blog.csdn.net/llzhh/article/details/52516591node
談談學到的東西:ide
1,set維護東西真的好用,好比維護還能更新的點spa
2,關於set的刪除 st.erase(iter).net
最後還要補充一下map和set的一點知識,就是若是你用erase刪除一個數字的時候,其實map和set封裝了紅黑樹在裏面,說白了就是個鏈表,可是網上好像是他們所用的空間是固定的,因此比通常的平衡樹效率要高,由於申請空間沒那麼費勁。那咱們從樹的角度出發,就是鏈表同樣,那麼若是你刪除了鏈表中一個節點,此時,再讓iter++尋找下一個節點,他是找不到的,由於那個節點已經被刪除了,本來節點空間裏面的東西全都是隨機生成的數字了,找下一個節點的時候都不知道飛到天上去了,那麼就會報錯。code
好比這樣blog
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按定位器刪除比按值刪除要快string
4,一個剪枝,if(st.empty())break;it
5,很差操做時,咱們能夠把將要刪除的東西放在一個隊列裏,等遍歷完後再進行按值刪除.
代碼:
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\n",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("\n"); 83 } 84 return 0; 85 }