zoukankan      html  css  js  c++  java
  • 题解 CF1338E JYPnation

    题目链接

    编了一个做法发现没人提出过,所以记录一下(

    直接考虑图强连通的情况。发现连向一个点的所有点一定构成一条链。于是考虑求出每个点到一号点的距离。

    考虑构造一棵 BFS 树。定义两个点 (x,y) 的小于关系,(x<y) 当且仅当:

    • 如果 (dis_x eq dis_y)(dis_x<dis_y)
    • 否则如果 (fa_x eq fa_y)(fa_x<fa_y)
    • 否则存在 (y o x) 的边

    然后每个点的父亲为 (dis) 恰好等于它减一的,它连向的,所有点中的最小的点。大约是如下的一棵树:

    将这张图按照给出的小于关系重标号之后,有一些非常好的性质:

    • (mx=fa_n),于是对于所有 (iin[2,mx-1]),都有 (fa_i=1)
    • 两个点 (j,i),如果 (fa_jleq i) 那么存在 (j o i) 的边,否则存在 (i o j) 的边

    一个直接的推论是这棵树的层数不会超过 (4),且所有第 (4) 层的节点的父亲都必须是第 (3) 层的第一个节点。

    于是不同的 (dis) 关系只会有 (6) 中,可以直接借此来讨论,复杂度 (mathcal O(n^2))

    #include<queue>
    #include<cstdio>
    #include<algorithm>
    
    const int maxn = 8005;
    
    int val[200];
    
    int n, deg[maxn], tot, buc[maxn];
    bool g[maxn][maxn], G[maxn][maxn], vis[maxn];
    int dis[maxn], p[maxn], rk[maxn], fa[maxn], son[maxn];
    
    bool chk[maxn][maxn], S[maxn][maxn];
    inline bool sml(int x, int y) {
    	if(x == y) return false;
    	if(chk[x][y]) return S[x][y];
    	
    	chk[x][y] = true;
    	if(dis[x] != dis[y]) return S[x][y] = dis[x] < dis[y];
    	if(fa[x] != fa[y]) return S[x][y] = sml(fa[x], fa[y]);
    	return S[x][y] = G[y][x];
    }
    
    std::vector<int> d[4];
    
    int main() {
    	val['0'] = 0, val['1'] = 1, val['2'] = 2, val['3'] = 3;
    	val['4'] = 4, val['5'] = 5, val['6'] = 6, val['7'] = 7;
    	val['8'] = 8, val['9'] = 9, val['A'] = 10, val['B'] = 11;
    	val['C'] = 12, val['D'] = 13, val['E'] = 14, val['F'] = 15;
    	
    	scanf("%d", &n);
    	for(int i = 1; i <= n; ++i) {
    		getchar();
    		for(int j = 1; j * 4 <= n; ++j) {
    			int v = val[getchar()];
    			g[i][j * 4 - 3] = v >> 3 & 1;
    			g[i][j * 4 - 2] = v >> 2 & 1;
    			g[i][j * 4 - 1] = v >> 1 & 1;
    			g[i][j * 4 - 0] = v >> 0 & 1;
    		}
    	}
    	
    	for(int i = 1; i <= n; ++i)
    		for(int j = 1; j <= n; ++j)
    			deg[j] += g[i][j];
    	
    	std::queue<int> q;
    	for(int i = 1; i <= n; ++i)
    		if(deg[i] == 0) q.push(i);
    	
    	int cnt = n; long long ans = 0;
    	while(!q.empty()) {
    		int u = q.front(); vis[u] = 1, q.pop();
    		
    		--cnt, ans += cnt * (1 + 614ll * n);
    		for(int i = 1; i <= n; ++i)
    			if(g[u][i] && !--deg[i]) q.push(i);
    	}
    	
    	for(int i = 1; i <= n; ++i)
    		if(!vis[i]) buc[++tot] = i;
    	
    	for(int i = 1; i <= tot; ++i) {
    		for(int j = 1; j <= tot; ++j)
    			G[i][j] = g[buc[i]][buc[j]];
    		G[i][i] = 1;
    	}
    	n = tot;
    	
    	std::fill(dis, dis + n + 1, 1E+9);
    	
    	q.push(1), dis[1] = 0;
    	while(!q.empty()) {
    		int u = q.front(); q.pop();
    		for(int i = 1; i <= n; ++i)
    			if(G[i][u] && dis[i] > dis[u] + 1)
    				dis[i] = dis[u] + 1, q.push(i);
    	}
    	
    	for(int i = 1; i <= n; ++i) d[dis[i]].push_back(i);
    	for(int i = 1; i <= 3; ++i)
    		for(int x : d[i]) {
    			for(int y : d[i - 1])
    				if(G[x][y] && (!fa[x] || sml(y, fa[x]))) fa[x] = y;
    			++son[fa[x]];
    		}
    	
    	for(int i = 1; i <= n; ++i) p[i] = i;
    	std::sort(p + 1, p + n + 1, sml);
    	for(int i = 1; i <= n; ++i) rk[p[i]] = i;
    	
    	for(int i = 1; i <= n; ++i) son[p[i]] += son[p[i - 1]];
    	
    	for(int i = 2; i <= n; ++i)
    		ans += dis[i] + 1 + (dis[i] == 1) + (son[i] == son[1]);
    	
    	for(int i = 2; i <= n; ++i) {
    		for(int j = i + 1; j <= n; ++j) {
    			int x = i, y = j;
    			
    			if(!sml(x, y)) std::swap(x, y);
    			if(dis[x] == 1 && dis[y] == 1) ans += 3 + (son[y] == son[x]);
    			if(dis[x] == 1 && dis[y] == 2) ans += 3;
    			if(dis[x] == 2 && dis[y] == 2) ans += 3 + (fa[x] == fa[y]);
    			if(dis[x] == 1 && dis[y] == 3) ans += 3 + sml(x, fa[fa[y]]);
    			if(dis[x] == 2 && dis[y] == 3) ans += 3 + sml(x, fa[y]);
    			if(dis[x] == 3 && dis[y] == 3) ans += 4;
    		}
    	}
    	
    	printf("%lld
    ", ans);
    }
    
  • 相关阅读:
    58:二叉树的下一个节点
    57:删除链表中重复的结点
    56:链表中环的入口结点
    55:字符流中第一个不重复的字符
    54:表示数值的字符串
    53:正则表达式匹配
    52:构建成绩数组
    51:数组中重复的数字
    每个努力奋斗过的人,被不公正的际遇砸了满头包的时候,都有那么一瞬间的代入感。出生就是hard模式的人,早已经历了太多的劳其筋骨饿其体肤,再多的人为考验只会摧毁人对美好的向往。
    ClientValidationEnabled
  • 原文地址:https://www.cnblogs.com/whx1003/p/14874791.html
Copyright © 2011-2022 走看看