• 洛谷P5068[Ynoi2015]我回来了(bfs+bitset)


    题目链接

    洛谷

    题外话

    这题的题目背景又让我想起了被致郁一周的恐惧……然后昨晚在床上就脑中重温了一遍……然后就又抑郁了一晚上……

    解析

    首先边权全为(1),那么就可以(O(n + m))(bfs)求单源最短路,每个点跑一遍(bfs),就可以(O(n(n + m)))求出任意两点间距离

    直接统计距离小于等于某个值的点不方便,我们考虑先统计恰好等于的点,然后只要前缀和就好了,但是如果只记录点的个数,前缀和就会算重

    要想正确求出答案,这个“前缀和”相当于“前缀集合并”,这种集合问题就可以考虑上(bitset)试试

    (f[i][j])是一个(bitset),表示到点(i),距离小于等于(j)的点的集合,每次(bfs)完统计恰好等于的情况,然后从(0)开始并上去就行了

    我们发现只有最多(1000)个点,距离也不会超过点数,那么(O(frac{n^3}{8}))的空间就开得下了

    然后大概(O(frac{n^3}{32}))的时间复杂度也是可以过掉这题的

    但是此题卡莲式前向星……因为内存不连续导致变慢,不如内存连续的(vector)快……

    代码

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <bitset>
    #include <vector>
    #define MAXN 1003
    #define MAXM 100003
    #define REG register
    
    typedef long long LL;
    const int inf = 0x3f3f3f3f;
    /*
    struct Graph {
    	struct Edge {
    		int v, next;
    		Edge(int _v = 0, int _n = 0):v(_v), next(_n) {}
    	} edge[MAXM << 1];
    	int head[MAXN], dist[MAXN], cnt;
    	void init() { memset(head, -1, sizeof head); cnt = 0; }
    	void add_edge(int u, int v) { edge[cnt] = Edge(v, head[u]); head[u] = cnt++; }
    	void insert(int u, int v) { add_edge(u, v); add_edge(v, u); }
    	void bfs(int);
    } G;
    */
    std::vector<int> next[MAXN];
    int N, M, Q, dist[MAXN];
    std::bitset<MAXN> f[MAXN][MAXN], ans;
    
    void bfs(int);
    char gc();
    int read();
    void print(int);
    int main() {
    	//G.init();
    	N = read(), M = read(), Q = read();
    	while (M--) {
    		int x = read(), y = read();
    		//G.insert(x, y);
    		next[x].push_back(y);
    		next[y].push_back(x);
    	}
    	for (REG int i = 1; i <= N; ++i) {
    		//G.bfs(i);
    		bfs(i);
    		for (REG int j = 1; j <= N; ++j) if (dist[j] ^ inf) f[i][dist[j]].set(j);
    		for (REG int j = 1; j <= N; ++j) f[i][j] |= f[i][j - 1];
    	}
    	while (Q--) {
    		ans.reset();
    		int a = read(), x, y;
    		while (a--) { x = read(), y = read(); ans |= f[x][std::min(y, N)]; }
    		print((int)ans.count()); putchar('
    ');
    	}
    
    	return 0;
    }
    //void Graph::bfs(int s) {
    void bfs(int s) {
    	memset(dist, inf, sizeof dist);
    	dist[s] = 0;
    	static int que[MAXN];
    	REG int hd = 0, tl = 0;
    	que[tl++] = s;
    	while (hd ^ tl) {
    		int p = que[hd++];
    		//for (REG int i = head[p]; ~i; i = edge[i].next)
    		for (REG int i = 0; i < next[p].size(); ++i)
    			if (dist[next[p][i]] == inf) {
    				dist[next[p][i]] = dist[p] + 1;
    				que[tl++] = next[p][i];
    			}
    	}
    }
    inline char gc() {
    	static char buf[1000000], *p1, *p2;
    	if (p1 == p2) p1 = (p2 = buf) + fread(buf, 1, 1000000, stdin);
    	return p1 == p2 ? EOF : *p2++;
    }
    inline int read() {
    	int res = 0; char ch = gc();
    	while (ch < '0' || ch > '9') ch = gc();
    	while (ch >= '0' && ch <= '9') res = (res << 1) + (res << 3) + ch - '0', ch = gc();
    	return res;
    }
    inline void print(int x) {
    	static int buf[20];
    	if (!x) putchar('0');
    	else {
    		while (x) buf[++buf[0]] = x % 10, x /= 10;
    		while (buf[0]) putchar('0' + buf[buf[0]--]);
    	}
    }
    //Rhein_E
    
  • 相关阅读:
    jfixed使固定行列可编辑表格
    Base 64 加密、解密
    去除富文本格式
    阿里移动安全挑战赛第二题研究小结
    CyanogenMod源码下载、编译、刷机过程记录(HTC buzz)
    编译民间安卓源码mokesoures4.2.2报错内容【解决了!】
    Linux下通过NDK的初步使用【详细步骤+截图】
    Linux下实现JNI期间发生的错误……【未解决】
    C++调用Java方法时jvm.dll相关错误 【每次记录完后都被瞬间解决了……】
    JNI学习中——JVM错误:EXCEPTION_ACCESS_VIOLATION (0xc0000005)
  • 原文地址:https://www.cnblogs.com/Rhein-E/p/10508413.html
Copyright © 2020-2023  润新知