• luogu1980 车站分级


    题目大意

      一些火车站排成一行。给出一些火车的停靠站情况,要求对每一个火车,其经过且不停靠的站的级别比它任意停靠的站的级别小。问所有车站最少需要多少个级别。

    题解

      不要只看到这道题的背景设立在一个区间上,就只想线段上的动规与贪心。由火车停靠站的情况可以得到不同站与不同站之间的级别满足偏序关系,这样就可以建立拓扑图求最长路径即可。

      普通建图$O(nm)$,要注意重边的情况,否则会MLE。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <cassert>
    using namespace std;
    
    const int MAX_NODE = 1010;
    
    struct TopGraph
    {
    private:
        struct Node
        {
            vector<Node*> Next;
            int Dist, DfsN;
        }_nodes[MAX_NODE];
        stack<Node*> St;
        int TotNode;
    
        void Dfs(Node *cur)
        {
            if (cur->DfsN == 2)
                return;
            assert(cur->DfsN != 1);
            cur->DfsN = 1;
            for (int i = 0; i < cur->Next.size(); i++)
                Dfs(cur->Next[i]);
            cur->DfsN = 2;
            St.push(cur);
        }
    
    public:
        void Init(int n)
        {
            TotNode = n;
        }
    
        void AddEdge(int u, int v)
        {
            _nodes[u].Next.push_back(_nodes + v);
        }
    
        int LongestPath()
        {
            for (int i = 1; i <= TotNode; i++)
                Dfs(_nodes + i);
            int ans = 0;
            while (!St.empty())
            {
                Node *cur = St.top();
                St.pop();
                ans = max(ans, cur->Dist);
                for (int i = 0; i < cur->Next.size(); i++)
                    cur->Next[i]->Dist = max(cur->Next[i]->Dist, cur->Dist + 1);
            }
            return ans;
        }
    }g;
    
    int stopPos[MAX_NODE];
    bool Vis[MAX_NODE][MAX_NODE];
    
    int main()
    {
        int len, trainCnt;
        scanf("%d%d", &len, &trainCnt);
        g.Init(len);
        for (int i = 1; i <= trainCnt; i++)
        {
            int stopCnt;
            scanf("%d", &stopCnt);
            for (int j = 1; j <= stopCnt; j++)
                scanf("%d", stopPos + j);
            for (int j = 1; j < stopCnt; j++)
                for (int k = stopPos[j] + 1; k <= stopPos[j + 1] - 1; k++)
                    for (int l = 1; l <= stopCnt; l++)
                    {
                        if (!Vis[k][stopPos[l]])
                        {
                            g.AddEdge(k, stopPos[l]);
                            Vis[k][stopPos[l]] = true;
                        }
                    }
        }
        printf("%d
    ", g.LongestPath() + 1);
        return 0;
    }
    

      $O(n)$算法,对每个火车建立一个虚点,所有经过不停靠的站向虚点连边权1的边,虚点向所有停靠站连边权0的边,与原方法等价,却减少了时间复杂度。 

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    #include <stack>
    #include <cassert>
    using namespace std;
    
    const int MAX_NODE = 2010;
    
    struct TopGraph
    {
    private:
    	struct Edge;
    
    	struct Node
    	{
    		Edge *Head;
    		int Dist, DfsN;
    	}_nodes[MAX_NODE];
    	stack<Node*> St;
    	int TotNode;
    
    	struct Edge
    	{
    		Node *To;
    		Edge *Next;
    		int Weight;
    	}_edges[MAX_NODE * MAX_NODE];
    	int _eCount;
    
    	void Dfs(Node *cur)
    	{
    		if (cur->DfsN == 2)
    			return;
    		assert(cur->DfsN != 1);
    		cur->DfsN = 1;
    		for (Edge *e = cur->Head; e; e = e->Next)
    			Dfs(e->To);
    		cur->DfsN = 2;
    		St.push(cur);
    	}
    
    public:
    	void Init(int n)
    	{
    		TotNode = n;
    	}
    
    	void AddEdge(int uId, int vId, int w)
    	{
    		Node *from = _nodes + uId, *to = _nodes + vId;
    		Edge *e = _edges + ++_eCount;
    		e->To = to;
    		e->Weight = w;
    		e->Next = from->Head;
    		from->Head = e;
    	}
    
    	int LongestPath()
    	{
    		for (int i = 1; i <= TotNode; i++)
    			Dfs(_nodes + i);
    		int ans = 0;
    		while (!St.empty())
    		{
    			Node *cur = St.top();
    			St.pop();
    			ans = max(ans, cur->Dist);
    			for (Edge *e = cur->Head; e; e = e->Next)
    				e->To->Dist = max(e->To->Dist, cur->Dist + e->Weight);
    		}
    		return ans;
    	}
    }g;
    
    int stopPos[MAX_NODE];
    
    int main()
    {
    	int len, trainCnt;
    	scanf("%d%d", &len, &trainCnt);
    	g.Init(len + trainCnt);
    	for (int i = 1; i <= trainCnt; i++)
    	{
    		int stopCnt;
    		scanf("%d", &stopCnt);
    		for (int j = 1; j <= stopCnt; j++)
    			scanf("%d", stopPos + j);
    		for (int j = 1; j < stopCnt; j++)
    			for (int k = stopPos[j] + 1; k <= stopPos[j + 1] - 1; k++)
    				g.AddEdge(k, len + i, 1);
    		for (int j = 1; j <= stopCnt; j++)
    			g.AddEdge(len + i, stopPos[j], 0);
    	}
    	printf("%d
    ", g.LongestPath() + 1);
    	return 0;
    }
    

      

  • 相关阅读:
    CentOS 7安装NXLog服务
    CentOS 7下Nginx日志的定时拆分
    IIS服务器配置NXLog进行syslog转发(并解决GMT+8小时时差问题)
    Linux服务器和Nginx配置syslog转发
    CentOS 7下安装Slowhttptest DDoS检测工具
    接口自动化:六.pytest写用例
    linux: CentOs 环境下搭建nginx负载均衡
    linux: CentOs 环境下搭建nginx
    环境搭建:linux下tomcat接口测试环境部署
    环境搭建:linux环境下安装mysql数库
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9492242.html
Copyright © 2020-2023  润新知