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的优化

模板详见:

关于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);
        }
    }
}
posted @ 2019-10-30 07:09  Seaway-Fu  阅读(459)  评论(0编辑  收藏  举报