Graph theory (Dijkstra, SPFA, Floyd, topology, Tarjan)

Shortest path
Dijkstra (Dijkstra) algorithm

T(n)=O(n^2)

void dijkstra()
{
    
    
    for (int i = 1; i <= n; i++)
    {
    
    
        flag[i] = 0;
        road[i] = uv[1][i];
    }
    road[1] = 0;
    flag[1] = 1;
    for (int i = 1; i < n; i++)
    {
    
    
        int minn = 0x7fffff;
        int t;
        for (int j = 1; j <= n; j++)
            if (flag[j] == 0 && road[j] < minn)
            {
    
    
                t = j;
                minn = road[j];
            }
        flag[t] = 1;
        for (int k = 1; k <= n; k++)
            road[k] = min(road[k], road[t] + uv[t][k]);
    }
}

//记录路径
void dfs(int v, int len)
{
    
    
    if (v == 1)
        return;
    for (int i = 1; i <= n; i++)
        if (uv[i][v] != 0x7fffff)
            if (road[v] - uv[i][v] == road[i])
            {
    
    
                x[++o] = v;
                y[o] = i;
                dfs(i, road[i]);
                return;
            }
}

Heap optimization + record path + record path number
Complexity: O((V+E)logE)----V is the number of edges, E is the number of points


ll n,m,s,e,tot;
ll head[maxn], tot, dis[maxn], vis[maxn],pre[maxn],cnt[maxn];
priority_queue<pair<ll,ll> >que;//格式化文档时这里易错

struct Edges
{
    
    
	ll from,to,dis,next;
}edges[maxm];

void add(ll x,ll y,ll dis)
{
    
    
	edges[++tot].next=head[x];
	edges[tot].to=y;
	edges[tot].dis=dis;
	head[x]=tot;
}

void Path(ll i)
{
    
    
    if (pre[i] == -1)
        return;
    else
        Path(pre[i]);
    printf("%lld ", pre[i]);
}

void dij()
{
    
    
	que.push(make_pair(0,s));
	while(!que.empty())
	{
    
    
		ll u=que.top().second;
		que.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(ll i=head[u];i;i=edges[i].next)
		{
    
    
			ll v=edges[i].to;
			if(dis[v]>dis[u]+edges[i].dis)
			{
    
    
				dis[v]=dis[u]+edges[i].dis;
				que.push(make_pair(-dis[v],v));//pair先比较第一个,后比较第二个
				//改成dis[v]传可按降序出队列,解决最长路问题
			}
			else if(dis[v] == dis[u] + edges[i].dis)
            {
    
    
                cnt[v]+=cnt[u];
            }
		}
	}
}


int main()
{
    
    
	// DEBUG;
	while(!que.empty()) que.pop();
	tot=0;
	memset(head,0,sizeof(head));
	memset(dis,INF,sizeof(dis));
	memset(vis,0,sizeof(vis));
	memset(cnt, 0, sizeof(cnt));
    memset(pre, -1, sizeof(pre));
	scanf("%lld%lld%lld%lld",&n,&m,&s,&e);
	for(ll i=1;i<=m;i++)
	{
    
    
		ll v,u,dis;
		scanf("%lld%lld%lld",&v,&u,&dis);
		add(v,u,dis);
		add(u,v,dis);
	}
	dis[s]=0;
    cnt[s]=1;
	dij();
	printf("%lld\n",dis[e]);
	printf("%lld\n", cnt[e]);
    Path(e);
    printf("%lld\n", e);
}

Floyd algorithm
multi-source shortest path
T(n)=O(n^3)


ll n, m,s,d;
ll dis[maxn][maxn], va[maxn][maxn], p[maxn][maxn];
ll arr[maxn];

void floyd()
{
    
    
    for (ll k = 1; k <= n; k++)
    {
    
    
        for (ll u = 1; u <= n; u++)
        {
    
    
            for (ll v = 1; v <= n; v++)
            {
    
    
                if (dis[u][v] > dis[u][k] + dis[k][v])
                {
    
    
                    dis[u][v] = dis[u][k] + dis[k][v];
                    va[u][v] = va[u][k] + va[k][v];
                    p[u][v] = p[u][k];
                }
                else if (dis[u][v] == dis[u][k] + dis[k][v] && va[u][v] < va[u][k] + va[k][v])
                {
    
    
                    va[u][v] = va[u][k] + va[k][v];
                    p[u][v] = p[u][k];
                }
            }
        }
    }
}

int main()
{
    
    
    // DEBUG;
    scanf("%lld%lld%lld%lld", &n, &m,&s,&d);
    for (ll i = 1; i <= n; i++)
    {
    
    
        for (ll j = 1; j <= n; j++)
        {
    
    
            p[i][j] = j;
            va[i][j] = 0;
            if (i != j)
                dis[i][j] = INF;
            else
                dis[i][j] = 0;
        }
    }
    for (ll i = 1; i <= m; i++)
    {
    
    
        ll u, v, w, val;
        scanf("%lld%lld%lld%lld", &u, &v, &w);
        dis[u][v] = w;
        va[u][v] = val;
        dis[v][u] = w;
        va[v][u] = val;
    }
    floyd();
    ll st, minres = INF;
    ll k;
    scanf("%lld", &k);
    for (ll i = 1; i <= k; i++)
    {
    
    
        scanf("%lld", &arr[i]);
    }
    for (ll i = 1; i <= n; i++)
    {
    
    
        ll res = 0;
        ll u = i;
        for (ll j = 1; j <= n; j++)
        {
    
    
            ll v = j;
            res = max(dis[u][v], res);
        }
        if (res < minres)
        {
    
    
            minres = res;
            st = u;
        }
    }
    printf("%lld\n", st);
    for (ll i = 1; i <= k; i++)
    {
    
    
        ll v = arr[i];
        printf("%lld", st);
        ll u = st;
        while (u != v)
        {
    
    
            printf("->%lld", p[u][v]);
            u = p[u][v];
        }
        printf("\n");
        printf("%lld %lld\n", dis[st][v], va[st][v]);
    }
    return 0;
}

SPFA Algorithm
Complexity: O(E)~O(VE)

ll head[maxn], tot, dis[maxn], vis[maxn], pre[maxn], cnt[maxn],cnt1[maxn];
ll n, m, s, e, x, y, z;
queue<ll> q; //用标准队列

struct Edge
{
    
    
    ll next, to, dis;
} edges[maxn]; //链式前向星存图

void add(ll x, ll y, ll z)
{
    
    
    edge[++tot].next = head[x];
    edge[tot].to = y;
    edge[tot].dis = z;
    head[x] = tot;
}

// 打印路径
void Path(ll i)
{
    
    
    if (pre[i] == -1)
        return;
    else
        Path(pre[i]);
    printf("%lld ", pre[i]);
}

void spfa()
{
    
    
    q.push(s);
    vis[s] = 1;//每次入队,vis标记为 1
    while (!q.empty())
    {
    
    
        x = q.front();
        q.pop();
        vis[x] = 0;//每次入队,vis标记为 0
        for (ll i = head[x]; i; i = edge[i].next)
        {
    
    
            y = edge[i].to;
            if (dis[y] > dis[x] + edge[i].dis)
            {
    
    
                dis[y] = dis[x] + edge[i].dis;
                pre[y] = x;
                cnt[y] = cnt[x];
                cnt1[y]++;
                if(cnt1[y]>n+10) return -1;//表示存在负环
                if (!vis[y])
                {
    
    
                    vis[y] = 1;
                    q.push(y);
                }
            }
            else if (dis[y] == dis[x] + edge[i].dis)
            {
    
    
                cnt[y] += cnt[x];
            }
        }
    }
}

int main()
{
    
    
    scanf("%lld%lld%lld", &n, &m, &s);
    for (ll i = 1; i <= m; i++)
    {
    
    
        scanf("%lld%lld%lld", &x, &y, &z);
        add(x, y, z);
    }
    memset(cnt, 0, sizeof(cnt)); //记录最短路径数
    memset(pre, -1, sizeof(pre));
    memset(dis, INF, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    dis[s] = 0; //初始化
    cnt[s] = 1;
    spfa();
    for (ll i = 1; i <= n; i++)
    {
    
    
        if (s == i)
            printf("0 ");
        else printf("%lld ", dis[i]);
    }
    printf("%lld\n", cnt[e]);
    Path(e);
    printf("%lld\n", e);
    return 0;
}

Topological sorting
complexity: O(V+E)

ll n,m;
ll ind[maxn];
ll res[maxn];
vector<ll> to[maxn];
queue<ll> que;

int main()
{
    
    
    // DEBUG;
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=m;i++)
    {
    
    
        ll u,v;
        scanf("%lld%lld",&u,&v);
        to[u].push_back(v);
        ind[v]++;
    }
    for(ll i=1;i<=n;i++)
    {
    
    
        if(ind[i]==0) que.push(i);
    }
    ll pos=0;
    while(!que.empty())
    {
    
    
        ll u=que.front();
        que.pop();
        res[++pos]=u;
        for(auto v:to[u])
        {
    
    
            ind[v]--;
            if(ind[v]==0) que.push(v);
        }
    }
    for(ll i=1;i<=n;i++)
    {
    
    
        printf("%lld\n",res[i]);
    }
}

Tarjan

struct Edge
{
    
    
    ll next, to, dis, from;
    double f;
} edges[maxm], E[maxm];

ll dfn[maxn], low[maxn], n, m, color[maxn], col = 0, w[maxn], s;
ll stackk[maxn], heads[maxn], visit[maxn], cnt, tot, index1, times;

ll H[maxn], tot1, dis[maxn], vis[maxn];
ll e, x, y, z;

priority_queue<pair<ll, ll>> que;

void add(ll x, ll y)
{
    
    
    edges[++tot].next = heads[x];
    edges[tot].from = x;
    edges[tot].to = y;
    heads[x] = tot;
    return;
}

void add2(ll x, ll y, ll z)
{
    
    
    E[++tot1].next = H[x];
    E[tot1].to = y;
    E[tot1].dis = z;
    H[x] = tot1;
}

void tarjan(ll x)
{
    
    
    dfn[x] = low[x] = ++times;
    visit[x] = 1;
    stackk[++index1] = x;
    for (ll i = heads[x]; i; i = edges[i].next)
    {
    
    
        if (!dfn[edges[i].to])
        {
    
    
            tarjan(edges[i].to);
            low[x] = min(low[x], low[edges[i].to]);
        }
        else if (visit[edges[i].to])
        {
    
    
            low[x] = min(low[x], dfn[edges[i].to]);
        }
    }
    if (low[x] == dfn[x])
    {
    
    
        col++;
        do
        {
    
    
            color[stackk[index1]] = col;
            visit[stackk[index1]] = 0;
            index1--;
        } while (x != stackk[index1 + 1]);
    }
}

int main()
{
    
    
    memset(heads, 0, sizeof(heads));
    ll n, m;
    scanf("%lld%lld", &n, &m);
    ll x, y;
    for (ll i = 1; i <= m; i++)
    {
    
    
        scanf("%lld%lld", &x, &y);
        add(x, y);
    }
    for (ll i = 1; i <= n; i++)
        if (!dfn[i])
            tarjan(i);
    for (ll i = 1; i <= m; i++)
    {
    
    
        if (color[edges[i].to] != color[edges[i].from])
        {
    
    
            ll id = color[edges[i].to];
            w[id] += edges[i].dis;
        }
        else
        {
    
    
            ll x = color[edges[i].from], y = color[edges[i].to];
            add2(x, y, edges[i].dis);
        }
    }
    return 0;
}

Guess you like

Origin blog.csdn.net/m0_51270992/article/details/115150855