CSP-S 2019图论总结
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);
}
}
}