图论

首先

\(\color {red}{SPFA已死,Dijkstra当立!}\)

\(\small{\color {gray}{咳}}\)

前向星

struct edge{int to,next,v;}e[N<<1];
int en,head[N];
void addedge(int x,int y,int v)
{
    e[++en]==(edge){y,head[x],v};
    head[x]=en;
}
void dfs(int x)
{
    for(int i=head[x];i;i=e[i].next;
    {
        int y=e[i].to;
        dfs(y);
    }
}

最短路图

1.没有负环
2.是DAG

bellman-ford

先将在、所有点的最短距离设为∞,起点为0(和dij一样)
然后对边集(边!)松弛两端端点
最后得记得检查一下
有了SPFA了要什么bellman-ford

SPFA

就是bellman-ford的priority_queue优化
\(\huge {但是}\)
\(\small {\color {grey}{它死了}}\)

正经点
就是在bellman-ford的基础上将遍历所有点改为直接从queue取数

int dis[N],inq[N];
void spfa()
{
    memeset(dis,0x3f,sizeof(dis);
    queue<int> q;
    q.push(1);
    inq[1]=1;
    dis[1]=0;
    while(!q.emptu())
    {
        int x=q.front();
        q.pop();
        inq[x]=0;
        for(int i=head[x];i;i=e[i].next)
        {
            int y=e[i].to;
            if(dis[y]>dis[x]+e[i].v)
            {
                dis[y]=dis[x]+e[i].v;
                if(!inq[y])
                {
                    q.push(y);
                    inq[y]=1;
                }
            }
        }
    }
}

把松弛的对比比较的大于号改成小于号就可以求最长路

  • \(\small {\color {white}{但是有了Dijkstra要什么SPFA}}\)

Dijkstra

Dij我之前写过,所以
点我滚过去_(:з」∠)_

拓扑排序

将当前入度最小的(联想到priority_queue)点向其他点探索,然后踢出去,找下一个入度最小的点,继续......
就这样

queue<int> q;
int rd[];//入度

void topsort()
{
    for(int i=1;i<=n;i++)
        if(rd[i]==0)
            q.push(i);
    while(!q.empty())
    {
        int x=q.front;
        q.pop();
        for(int i=head[x];i;i=e[i].next)
        {
            int y=e[i].to;
            rd[y]--;
            if(rd[y]==0)
                q.push(y);
        }
    }
}

Floyd

经典老算法
时间复杂度\(O(n^3)\)
太经典了
不过第三维可以省掉了

for(int k=1;k<=n;k++)
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
            f[i][j]=min(f[i][j],f[i][j]+f[k][j]);
    }
}

可以做传递闭包,可以跑得飞快

负环

1.负环可以用SPFA来判断($\small {SPFA突然又活了})
不过要把SPFA改成dfs,但是可能会当场T掉(如果出题人很恶心)
2.或者记录每个点的入队次数,只要有点入队次数大于n那就有负环
3.还有一个,开一个数组记录当前最短路有几个点,如果大于n,那就存在负环
在对比之下,1会被卡爆,2比3慢一些,所以用3

bool spfa()
{
    queue<int> q;
    memset(dis,0x3f,sizeof(dis));
    memset(cnt,0,sizeof(cnt));
    memset(inq,0,sizeof(inq));
    dis[1]=0;
    q.push(1);
    inq[1]=cnt[1]=1;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        inq[x]=0;
        for(int i=1;i;i=e[i].next)
        {
            int y=e[i].to;
            if(dis[y]>dis[x]+e[i].v)
            {
                cnt[y]=cnt[x]+1;
                if(cnt[y]>n)
                    return true;
                dis[y]=dis[x]+e[i].v;
                if(!inq[y])
                {
                    q.push(y);
                    inq[y]=1;
                }
            }
        }
    }
    return false;
}
posted @ 2019-07-08 09:06  ComputerEngine  阅读(132)  评论(0编辑  收藏  举报