zoukankan      html  css  js  c++  java
  • [ZJOI2012]灾难

    首先抽象一个超级源点S,他向所有源点都有一条有向边。然后就是建立一棵树,使得这棵树满足对于每个节点,在有向可拓扑图中说删掉他而使得源点不可达的节点都是以他为根的这棵子树中的节点。

          建立这棵树的做法就是先将原图拓扑排序一次,然后按照拓扑序依次处理每个点,由于拓扑序的原因,每当处理到一个点,当前点的父节点一定在当前已建的树上,然后当前点的所有食物在这棵树上的最近公共祖先就是当前点的父节点。

    /**
     * Problem:catas
     * Author:Shun Yao
     * Time:2013.6.3
     * Result:Accepted
     * Memo:graphs
     */
    
    #include <cstring>
    #include <cstdio>
    
    void swap(long &x, long &y) {
    	if (x == y)
    		return;
    	x ^= y;
    	y ^= x;
    	x ^= y;
    }
    
    const long Maxn = 65555;
    
    long n, d[Maxn], fa[Maxn], ans[Maxn], du[Maxn];
    
    class gnode {
    public:
    	long v;
    	gnode *next;
    	gnode() {}
    	~gnode() {}
    	gnode(long V, gnode *ne):v(V), next(ne) {}
    } *g[Maxn], *G[Maxn], *gg[Maxn];
    void addg(long x, long y) {
    	g[x] = new gnode(y, g[x]);
    }
    void addG(long x, long y) {
    	G[x] = new gnode(y, G[x]);
    }
    void addgg(long x, long y) {
    	gg[x] = new gnode(y, gg[x]);
    }
    
    long get(long x, long y) {
    	if (d[x] < d[y])
    		swap(x, y);
    	while (d[x] > d[y])
    		x = fa[x];
    	while (x != y) {
    		x = fa[x];
    		y = fa[y];
    	}
    	return x;
    }
    
    long q[Maxn], *l, *r;
    int main() {
    	static long i, a;
    	static gnode *e;
    	freopen("catas.in", "r", stdin);
    	freopen("catas.out", "w", stdout);
    	scanf("%ld", &n);
    	for (i = 1; i <= n; ++i) {
    		du[i] = 0;
    		while (scanf("%ld", &a), a) {
    			addg(i, a);
    			addG(a, i);
    			++du[i];
    		}
    	}
    	r = l = q;
    	for (i = 1; i <= n; ++i)
    		if (du[i] == 0)
    			*(r++) = i;
    	while (l != r) {
    		for (e = G[*l]; e; e = e->next)
    			if (!--du[e->v])
    				*(r++) = e->v;
    		++l;
    	}
    	memset(d, 0, sizeof d);
    	l = q;
    	while (l != r) {
    		if (g[*l]) {
    			a = g[*l]->v;
    			for (e = g[*l]->next; e; e = e->next)
    				a = get(a, e->v);
    			addgg(a, *l);
    			fa[*l] = a;
    			d[*l] = d[a] + 1;
    		} else {
    			addgg(0, *l);
    			fa[*l] = 0;
    			d[*l] = 1;
    		}
    		++l;
    	}
    	l = r;
    	do {
    		--l;
    		ans[*l] = 1;
    		for (e = gg[*l]; e; e = e->next)
    			ans[*l] += ans[e->v];
    	} while (l != q);
    	printf("%ld", ans[1] - 1);
    	for (i = 2; i <= n; ++i)
    		printf("\n%ld", ans[i] - 1);
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    C++学习9 this指针详解
    福建省第八届 Triangles
    UVA 11584 Partitioning by Palindromes
    POJ 2752 Seek the Name, Seek the Fame
    UVA 11437 Triangle Fun
    UVA 11488 Hyper Prefix Sets (字典树)
    HDU 2988 Dark roads(kruskal模板题)
    HDU 1385 Minimum Transport Cost
    HDU 2112 HDU Today
    HDU 1548 A strange lift(最短路&&bfs)
  • 原文地址:https://www.cnblogs.com/hsuppr/p/3115527.html
Copyright © 2011-2022 走看看