• luogu P3119 [USACO15JAN]Grass Cownoisseur G 有向图强连通分量+分层最短路


    #include<cstdio>
    #include<queue>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N = 400005;
    int n, m;
    int h[N], e[N], ne[N], idx;
    int dfn[N], low[N], timestamp;
    int stk[N], top;
    bool in_stk[N];
    int id[N];
    int scc_cnt;
    int Size[N];
    int dout[N];
    int u[N],v[N];
    void add(int a, int b)
    {
    	e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
    }
    void tarjan(int u)
    {
    	dfn[u] = low[u] = ++ timestamp;
    	stk[ ++ top] = u;
    	in_stk[u] = true;
    	for (int i = h[u]; i != -1; i = ne[i])
    	{
    		int j = e[i];
    		if (!dfn[j])
    		{
    			tarjan(j);
    			low[u] = min(low[u], low[j]);
    		}
    		else if (in_stk[j])
    			//取最小
    			low[u] = min(low[u], dfn[j]);
    	}
    	if (dfn[u] == low[u])
    	{
    		++ scc_cnt;
    		int y;
    		do
    		{
    			y = stk[top -- ];
    			in_stk[y] = false;
    			id[y] = scc_cnt;
    			Size[scc_cnt] ++ ;
    		}
    		while (y != u);
    	}
    }
    int dis[N];
    int vis[N];
    queue<int>q;
    void spfa()
    {
    	memset(dis,-100,sizeof dis);
    	memset(vis,0,sizeof vis);
    	q.push(id[1]);
    	dis[id[1]]=0;
    	vis[id[1]]=1;
    	while(q.size())
    	{
    		int u=q.front();
    		q.pop();
    		vis[u]=0;
    		for(int i=h[u]; i!=-1; i=ne[i])
    		{
    			int v=e[i];
    			if(dis[v]<dis[u]+Size[u])
    			{
    				dis[v]=dis[u]+Size[u];
    				if(!vis[v])
    				{
    					q.push(v);
    					vis[v]=1;
    				}
    			}
    		}
    	}
    }
    int main()
    {
    	cin>>n>>m;
    	memset(h, -1, sizeof h);
    	for(int i=1; i<=m; i++)
    	{
    		int a, b;
    		cin>>a>>b;
    		u[i]=a,v[i]=b;
    		add(a, b);
    	}
    	for (int i = 1; i <= n; i ++ )
    		if (!dfn[i])
    			tarjan(i);
    	memset(h,-1,sizeof h);
    	for(int i=1; i<=m; i++)
    	{
    		if(id[u[i]]==id[v[i]])
    			continue;
    		//正向边 
    		add(id[u[i]],id[v[i]]);
    		add(id[u[i]]+n,id[v[i]]+n);
    		//反向边,只能走一次 
    		add(id[v[i]],id[u[i]]+n);
    	}
    	for(int i=1; i<=scc_cnt; i++)
    		Size[i+n]=Size[i];
    	spfa();
    	cout<<max(dis[id[1]],dis[id[1]+n])<<endl;
    	return 0;
    }
    
  • 相关阅读:
    MySQL数据库高并发优化配置
    MySQL性能参数详解
    jQuery中过滤选择器first和first-child的区别
    Linux非常用命令
    jps命令学习
    通过乐观锁(版本号)降低并发时的锁竞争
    ReentrantLock 相关学习笔记
    grep 所有多个关键字
    ThreadLocal学习笔记
    Idea设置全白色 背景
  • 原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12924438.html
Copyright © 2020-2023  润新知