zoukankan      html  css  js  c++  java
  • 洛谷1983 车站分级

    原题链接

    设某一趟车所停靠的车站的集合为(S = {a_1,a_2,dots, a_{k - 1}, a_k}),那么对于一个车站(forall xin (a_1, a_k), otin S),向集合(S)中的每一个车站连一条边权为(1)的有向边,表示停靠的车站比未停靠高一级。
    最后在建好的图上跑拓扑排序找最长链,答案就是最长链的长度(+1)(基础一个分级)。
    而若是暴力建图,复杂度为(O(nm^2)),理论上无法过掉此题,但这题貌似数据比较水,可过。
    这里我采用链表的形式,建立一个长度为(n)的链表,对于每一趟车,将其停靠的车站从链表里删去,这样最坏复杂度为(O(frac{4}{nm^2})),虽然理论上也是不能过此题,但因为一般的数据不会到达上界,且该题数据又很水,所以飞快地跑过了此题。。

    #include<cstdio>
    using namespace std;
    const int N = 1010;
    const int M = 1e6 + 10;
    struct dd{
    	int pre, suc;
    };
    dd b[N];
    int fi[N], di[M], ne[M], a[N], ru[N], q[M], dis[N], l, n;
    bool v[N][N];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline void add(int x, int y)
    {
    	di[++l] = y;
    	ne[l] = fi[x];
    	fi[x] = l;
    }
    inline void con(int x)
    {
    	b[x].pre = x - 1;
    	b[x].suc = x + 1;
    }
    inline void de(int x)
    {
    	b[b[x].pre].suc = b[x].suc;
    	b[b[x].suc].pre = b[x].pre;
    }
    inline int maxn(int x, int y)
    {
    	return x > y ? x : y;
    }
    int topsort()
    {
    	int i, x, y, head = 0, tail = 0, ma = 0;
    	for (i = 1; i <= n; i++)
    		if (!ru[i])
    			q[++tail] = i;
    	while (head ^ tail)
    	{
    		x = q[++head];
    		for (i = fi[x]; i; i = ne[i])
    		{
    			y = di[i];
    			if (!(--ru[y]))
    				q[++tail] = y;
    			dis[y] = maxn(dis[y], dis[x] + 1);
    			ma = maxn(ma, dis[y]);
    		}
    	}
    	return ma;
    }
    int main()
    {
    	int i, j, m, k, o;
    	n = re();
    	m = re();
    	for (i = 1; i <= m; i++)
    	{
    		for (j = 1; j <= n; j++)
    			con(j);
    		o = re();
    		a[1] = re();
    		for (j = 2; j <= o; j++)
    		{
    			a[j] = re();
    			de(a[j]);
    		}
    		for (j = b[a[1]].suc; j <= a[o] && j; j = b[j].suc)
    			for (k = 1; k <= o; k++)
    				if (!v[j][a[k]])
    				{
    					v[j][a[k]] = 1;
    					add(j, a[k]);
    					ru[a[k]]++;
    				}
    	}
    	printf("%d", topsort() + 1);
    	return 0;
    }
    
  • 相关阅读:
    C++类的内存结构
    emplace与insert的区别(C++11)
    C/C++宏的奇技淫巧
    编译器对内存的分配
    利用C++实现模块隐藏(R3层断链)
    PCB标准规范
    RTC 总结
    0.96寸OLED显示屏 IIC接口(SSD1306)
    串行通信简介(SPI, IIC, UART)
    人生感悟
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/9798235.html
Copyright © 2011-2022 走看看