CSP-S 2019图论总结
一、最短路问题
模板
Floyd算法
void floyd() { memset(map,0x3f,sizeof(map)); for(int i=1;i<=n;i++) map[i][i]=0; for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) map[i][j]=min(map[i][j],map[i][k]+map[k][j]); }
Dijkstra算法
const int INF=1e9; void dijkstra(int s) { int temp,k,y; memset(dist,0x3f,sizeof(dist)); memset(v,0,sizeof(v)); dist[s]=0; for(int i=1;i<=n;i++) { temp=INF; for(int j=1;j<=n;j++) if(dist[j]<temp && !v[j]) k=j,temp=dist[j]; v[k]=1; for(int j=head[i];j;j=nxt[j]) { y=to[i]; if(dist[y]>dist[k]+val[j]) dist[y]=dist[k]+val[j]; } } }
SPFA算法
void spfa(int s) { memset(dist,0x3f,sizeof(dist)); memset(v,0,sizeof(v)); queue<int> q; q.push(s);v[s]=1;dist[s]=0; while(!q.empty()) { int x=q.front(); v[x]=0;q.pop(); for(int i=head[x];i;i=nxt[i]) { int y=to[i]; if(dist[y]>dist[x]+val[i]) { dist[y]=dist[x]+val[i]; if(!v[y]) v[y]=1,q.push(y); } } } }
堆优化Dijkstra算法
void dijkstra() { memset(dist,0x3f,sizeof(dist)); dist[0]=0; q.push(make_pair(0,0)); while(!q.empty()) { int x=q.top().second; if(v[x]) { q.pop(); continue; } x=q.top().second;q.pop();v[x]=1; for(int i=head[x];i;i=nxt[i]) { int y=to[i]; if(dist[y]>dist[x]+val[i]) dist[y]=dist[x]+val[i],q.push(make_pair(-dist[y],y)); } } }
SPFA的优化
模板详见:
常见问题及解决方法
1、各种最短路算法的选择及应用(分析复杂度,拍熟模板、弄清楚这几种算法不能解决什么问题)
2、依据题意灵活建图(例题:VIJOS-P1423 最佳路线)
3、反向建图及反向建图的应用(例题:[NOIP2009]最优贸易 T3)
4、第K短路问题
5、最短路和DP的结合(例题:[ZJOI2006]物流运输)
6、最短路的优化(例题:[USACO10DEC]苹果交货Apple Delivery)
7、多重最短路问题(例题:[USACO14OPEN]GPS的决斗Dueling GPS's)
8、对偶边的处理
9、最短路路径记录
二、生成树问题
模板
Kruskal算法
void kruskal() { sort(e+1,e+m+1,cmp); for(int i=1;i<=m;i++) { int fx=find(e[i].x); int fy=find(e[i].y); if(fx!=fy) { fa[fx]=fy; cnt++; } if(cnt==n-1) return; } }
Prim算法
void prim() { memset(f,0x3f,sizeof(f)); memset(v,0,sizeof(v)); f[1]=0;v[1]=1; for(int i=1;i<=n;i++) { int temp=1<<30,k; for(int j=1;j<=n;j++) if(!v[j]&&f[j]<temp) temp=f[j],k=j; v[k]=1; ans+=f[k]; for(int j=head[k];j;j=nxt[j]) { int y=to[j]; if(val[j] && !v[j] && f[j]>val[j]) f[j]=val[j]; } } }
常见问题及解决方法
1、多重生成树(例题:JDOJ 1044 Span、[HNOI2006]公路修建问题)
2、树的拆分(例题:VIJOS-P1234 口袋的天空)
3、加边成树问题(例题:[USACO07DEC]道路建设Building Roads)
三、并查集
常见问题及解决方法
1、并查集对环的处理
2、并查集维护对立性(例题:[BOI2003]团伙)
3、带权并查集(例题:[NOI2002]银河英雄传说)
4、种类并查集(例题:[NOI2001]食物链)
四、拓扑排序
模板:
void topsort() { while(!q.empty()) { int x=q.front(); q.pop(); for(int i=head[x];i;i=nxt[i]) { int y=to[i]; if(y==fa[x]) continue; out_degree[y]--; if(!out_degree[y]) q.push(y); } } }