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;
    }
    
  • 相关阅读:
    EL表达式学习
    IDEA maven项目创建速度慢
    c语言栈的链表实现
    c数据结构学习随笔
    自定义JSP中的Taglib标签之四自定义标签中的Function函数
    深入理解HTTP Session
    利用GeneratedKeyHolder获得新增数据主键值
    RBAC用户角色权限设计方案
    Fragment与Activity交互(使用接口)
    php session 自定义的设置测试
  • 原文地址:https://www.cnblogs.com/hsuppr/p/3115527.html
Copyright © 2011-2022 走看看