• 【luogu P2169 正则表达式】 题解


    题目链接:https://www.luogu.org/problemnew/show/P2169
    tarjan缩点 + SPFA
    缩完点之后加边注意别写错。
    也可以不用建两个图,可以在一张图上判断是否强连通再SPFA.

    #include <queue>
    #include <stack>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn = 1000000 + 10;
    const int inf = 0x7fffffff;
    struct edge{
    	int from, to, next, len;
    }e1[maxn<<2], e2[maxn<<2];
    int head1[maxn], head2[maxn], cnt1, cnt2;
    int dfn[maxn], low[maxn], dis[maxn], tim;
    bool vis1[maxn], vis2[maxn];
    int n, m, color[maxn], num;
    stack<int> s;
    queue<int> q; 
    void add1(int u, int v, int w)
    {
    	e1[++cnt1].from = u;
    	e1[cnt1].len = w;
    	e1[cnt1].next = head1[u];
    	e1[cnt1].to = v;
    	head1[u] = cnt1;
    }
    void add2(int u, int v, int w)
    {
    	e2[++cnt2].from = u;
    	e2[cnt2].len = w;
    	e2[cnt2].next = head2[u];
    	e2[cnt2].to = v;
    	head2[u] = cnt2;
    }
    void tarjan(int x)
    {
    	dfn[x] = low[x] = ++tim;
    	s.push(x); vis1[x] = 1;
    	for(int i = head1[x]; i != -1; i = e1[i].next)
    	{
    		int v = e1[i].to;
    		if(!dfn[v])
    		{
    			tarjan(v);
    			low[x] = min(low[x], low[v]);
    		}
    		else if(vis1[v])
    		{
    			low[x] = min(low[x], low[v]);
    		}
    	}
    	if(low[x] == dfn[x])
    	{
    		color[x] = ++num;
    		vis1[x] = 0;
    		while(s.top() != x)
    		{
    			color[s.top()] = num;
    			vis1[s.top()] = 0;
    			s.pop();
    		}
    		s.pop();
    	}
    }
    void SPFA()
    {
    	while(!q.empty())
    	{
    		int now = q.front(); q.pop();
    		vis2[now] = 0;
    		for(int i = head2[now]; i != -1; i = e2[i].next)
    		{
    			int v = e2[i].to;
    			if(dis[v] > dis[now] + e2[i].len)
    			{
    				dis[v] = dis[now] + e2[i].len;
    				if(!vis2[v])
    				{
    					q.push(v);
    					vis2[v] = 1;
    				}
    			}
    		}
    	}
    }
    int main()
    {
    	memset(head1, -1, sizeof(head1));
    	memset(head2, -1, sizeof(head2));
    	scanf("%d%d",&n,&m);
    	for(int i = 1; i <= n; i++) dis[i] = inf;
    	for(int i = 1; i <= m; i++)
    	{
    		int u, v, w;
    		scanf("%d%d%d",&u,&v,&w);
    		add1(u,v,w);
    	}
    	for(int i = 1; i <= n; i++) 
    	if(!dfn[i]) tarjan(i);
    	for(int i = 1; i <= n; i++)
    		for(int j = head1[i]; j != -1; j = e1[j].next)
    		{
    			int v = e1[j].to;
    			if(color[v] != color[i])
    			add2(color[i], color[v], e1[j].len);
    		}
    	q.push(color[1]);
    	dis[color[1]] = 0;
    	vis2[color[1]] = 1;
    	SPFA();
    	printf("%d",dis[color[n]]);
    }
    
  • 相关阅读:
    css 实现换肤几种方式
    vue 使用中的小技巧 (一)
    GitLab集成Jenkins、Harborn构建pipeline流水线任务
    GitLab数据迁移
    Jenkins更换国内插件源以及Jenkins更新(Jenkins部署在Docker中)
    docker-compose安装JenKins
    docker-compose安装Nexus
    docker-compose安装GitLab
    安装Harbor并修改默认使用的80端口
    在CentOS7.5中基于docker-compose安装mysql5.7
  • 原文地址:https://www.cnblogs.com/MisakaAzusa/p/9368210.html
Copyright © 2020-2023  润新知