码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces - 1239D Catowice City

时间:2020-06-19 12:26:07      阅读:46      评论:0      收藏:0      [点我收藏+]

标签:int   tin   ORC   ret   std   getc   city   include   const   

博主的 BiBi 时间

这已经成为了一个固定栏目。。。其实也没有什么要说的。。。

Solution

感觉这题的建边不太一样。

我们输入 \(u,v\),连一条 \((u,v)\) 间的有向边表示 \(u\) 选了人, \(v\) 必须选人。(\(u,v\) 相等时不连边)

考虑这样连出来的一张图是什么。我们将这张图分成几个强连通分量,令强连通分量 \(x\) 连向强连通分量 \(y\)

对于每个强连通分量,要么全选??,要么全选人。

如果 \(x\) 全选??,对 \(y\) 的选择是没有影响的,而如果 \(x\) 全选人,\(y\) 也必须全选人。显然后面一种情况是没有意义的,因为我们必须保证有??又有人,对每种生物个数不做要求。

所以我们选择出度为零的那个强连通分量全选人即可。(如果有多个强连通分量,必定有一个出度为零,不然就只有一个了)

Code

有点卡时间,我在洛谷上开了 \(\mathtt{O2}\) + 手动清零才过。

#include <cstdio>

const int N = 1e6 + 5;

int n, m, siz[N], be[N], head[N], Head[N], cnt, tot, scc[N], to[N << 1], nxt[N << 1];
bool vis[N];

int read() {
    int x = 0, f = 1; char s;
    while((s = getchar()) > ‘9‘ || s < ‘0‘) if(s == ‘-‘) f = -1;
    while(s >= ‘0‘ && s <= ‘9‘) x = (x << 1) + (x << 3) + (s ^ 48), s = getchar();
    return x * f;
}

void addEdge(const int u, const int v) {
    to[++ cnt] = v, nxt[cnt] = head[u], head[u] = cnt;
    to[++ cnt] = u, nxt[cnt] = Head[v], Head[v] = cnt;
}

void dfs1(const int u) {
    vis[u] = 1;
    for(int i = head[u]; i; i = nxt[i])
        if(! vis[to[i]]) dfs1(to[i]);
    scc[++ tot] = u;
}

void dfs2(const int u) {
    vis[u] = 1; be[u] = tot; ++ siz[tot];
    for(int i = Head[u]; i; i = nxt[i])
        if(! vis[to[i]]) dfs2(to[i]);
}

void Kosaraju() {
    for(int i = 1; i <= n; ++ i) vis[i] = 0; tot = 0;
    for(int i = 1; i <= n; ++ i) if(! vis[i]) dfs1(i);
    for(int i = 1; i <= n; ++ i) vis[i] = 0; tot = 0;
    for(int i = n; i; -- i)
        if(! vis[scc[i]]) ++ tot, dfs2(scc[i]);
}

int main() {
	int u, v, lim;
	for(int T = read(); T; -- T) {
		n = read(), m = read(); cnt = 0;
		for(int i = 1; i <= n; ++ i) head[i] = Head[i] = siz[i] = 0;
		for(int i = 1; i <= m; ++ i) {
			u = read(), v = read();
			if(u == v) continue;
			addEdge(u, v);
		}
		if(! cnt && n == 1) {puts("NO"); continue;}
		if(! cnt) {
			printf("YES\n1 %d\n1\n", n - 1);
			for(int i = 2; i <= n; ++ i) printf("%d ", i);
			puts("");
			continue;
		}
		Kosaraju();
		if(tot > 1) {
			printf("YES\n%d %d\n", siz[tot], n - siz[tot]);
			for(int i = 1; i <= n; ++ i) if(be[i] == tot) printf("%d ", i);
			puts("");
			for(int i = 1; i <= n; ++ i) if(be[i] != tot) printf("%d ", i);
			puts("");
		}
		else puts("NO");
	}
	return 0;
}

CodeForces - 1239D Catowice City

标签:int   tin   ORC   ret   std   getc   city   include   const   

原文地址:https://www.cnblogs.com/AWhiteWall/p/13161969.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!