列表

详情


NC210354. 旅行

描述

皮卡丘所生活的国家有 n 个城市,可以分别用  表示;一共有 m 条单行道连接着这 n 个城市。每条单行道 (u,v) 表示生活在城市 u 的神奇宝贝可以到达城市 v,但生活在城市 v 的神奇宝贝不能通过这条单行道到达城市 u 。

皮卡丘计划了许多旅行方案:每个旅行方案 [u,v] 表示城市 u 是出发站,城市 v 是终点站。但有些旅行方案存在缺陷,即从出发站出发后无法到达终点站,这样的方案我们称作为不好的(Bad)方案,否则称为好的(Good)方案。

聪明的你能否帮助皮卡丘判断每一个旅行方案是好是坏呢?

除样例外,所有的测试数据中的道路和方案均随机生成。生成测试数据的 C++ 代码如下:

unsigned int seed; unsigned int xorshift32() {   unsigned int x = seed;   x ^= x << 13;   x ^= x >> 17;   x ^= x << 5;   return seed = x; } void gen(int n, int m, int q) {   // n: number of vertices   // m: number of edges   // q: number of queries   // initialize the seed with a random value.   cout << n << ' ' << m << endl;   for (int i = 0, u, v; i < m; i++) {     u = xorshift32() % n;     v = xorshift32() % n;     cout << u << ' ' << v << endl;   }   cout << q << endl;   for (int i = 0, u, v; i < q; i++) {     u = xorshift32() % n;     v = xorshift32() % n;     cout << u << ' ' << v << endl;   } }

输入描述

第一行输入两个整数 n,m (, ),分别表示城市的数量和道路的数量。

接下来输入 m 行,每行输入两个整数 u,v (),表示一条单行道 (u,v)。

第 m + 2 行输入一个整数 q (),表示方案的数量。

接下来输入 q 行,每行输入两个整数 x, y (),表示一组旅行方案。

输出描述

对于每一种方案,在一行输出 Good 或 Bad 表示这个方案的好坏。

示例1

输入:

11 12
0 1
0 2
1 3
2 4
2 5
3 6
3 7
4 8
4 9
5 10
5 4
8 1
5
0 7
9 1
2 1
5 6
10 8

输出:

Good
Bad
Good
Good
Bad

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 1291ms, 内存消耗: 49424K, 提交时间: 2020-08-05 16:53:17

#include<bits/stdc++.h>
using namespace std;
const int maxn=200009;

int n,m,T;
vector<int>G[maxn];

int siz[maxn];

int stk[maxn],top;
int dfsclock,scccnt;
int pre[maxn],lowlink[maxn],sccno[maxn];
void dfs(int u){
	pre[u]=lowlink[u]=++dfsclock;
	stk[++top]=u;
	for(int i=0;i<G[u].size();++i){
		int v=G[u][i];
		if(!pre[v]){
			dfs(v);
			lowlink[u]=min(lowlink[u],lowlink[v]);
		}else if(!sccno[v]){
			lowlink[u]=min(lowlink[u],pre[v]);
		}
	}
	
	if(lowlink[u]==pre[u]){
		++scccnt;
		for(;;){
			int x=stk[top--];
			sccno[x]=scccnt;
			if(x==u)break;
		}
	}
}

vector<int>G2[maxn];
int vis[maxn];

const int B=1000;
bitset<B+9>f[100009];
void dfs2(int x){
	if(vis[x])return;
	vis[x]=1;
	for(int i=0;i<G2[x].size();++i){
		int v=G2[x][i];
		dfs2(v);
		f[x]|=f[v];
	}
}


unordered_set<int>K[maxn];
int read(){
	int r=0,k=1;
	char c=getchar();
	for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
	for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';
	return r*k;
}

int qx[2*maxn],qy[2*maxn];
int ans[2*maxn];
int main(){
	scanf("%d%d",&n,&m);
	while(m--){
		int x=read()+1,y=read()+1;
		G[x].push_back(y);
	}
	for(int i=1;i<=n;++i)if(!pre[i])dfs(i);
	for(int i=1;i<=n;++i){
		for(int j=0;j<G[i].size();++j){
			int v=G[i][j];
			if(sccno[i]!=sccno[v]&&!K[sccno[i]].count(sccno[v])){
				G2[sccno[i]].push_back(sccno[v]);
				K[sccno[i]].insert(sccno[v]);
			}
		}
	}
	
	scanf("%d",&T);
	
	for(int i=1;i<=T;++i){
		qx[i]=sccno[read()+1];qy[i]=sccno[read()+1];
	}
	for(int k=0;;++k){
		if(k*B+1>scccnt)break;
		for(int i=1;i<=scccnt;++i){
			f[i].reset();vis[i]=0;
		}
		for(int i=1;i<=B;++i)f[k*B+i].set(i,1);
		for(int i=1;i<=scccnt;++i)dfs2(i);
		for(int i=1;i<=T;++i){
			if(qy[i]<=k*B||qy[i]>(k+1)*B)continue;
			int t=qy[i]-B*k;
			if(f[qx[i]][t])ans[i]=1;else ans[i]=0;
		}
	}
	for(int i=1;i<=T;++i){
		if(ans[i]){
			printf("Good\n");
		}else{
			printf("Bad\n");
		}
	}
	return 0;
}

C++14(g++5.4) 解法, 执行用时: 614ms, 内存消耗: 21300K, 提交时间: 2020-08-06 17:56:34

#include <bits/stdc++.h>
#define pb push_back
#define fi first
#define se second
using namespace std;
using pii = pair<int, int>;
const int N = 1e5 + 5, M = 405;
vector<int> G[N], DAG[N];
vector<pii> edges;
int n, m, _;
int dfn[N], num[N], low[N], id, tot, sta[N], top, deg[N], idx[N];
bool in[N];
int vis[N], spe[N];
bitset<N> bit[M];
void tarjan(int u)
{
	in[u] = 1;
	low[u] = dfn[u] = ++id;
	sta[++top] = u;
	for(int v : G[u])
	{
		if(!dfn[v])
		{
			tarjan(v);
			low[u] = min(low[u],low[v]);
		}
		else if(in[v]) low[u] = min(low[u],dfn[v]);
	}
	if(low[u]==dfn[u])
	{
		tot++;
		while(top)
		{
			int tmp = sta[top--];
			in[tmp] = 0;
			num[tmp] = tot;
			if(tmp==u) break;
		}
	}
}
void dfs(int u, int t)
{
	if(spe[u]) { bit[t] |= bit[spe[u]]; return; }
	vis[u] = t;
	bit[t].set(u);
	for(int v : DAG[u])
	{
		if(vis[v]==t) continue;
		dfs(v, t);
	}
}
void prework()
{
	for(int i=1; i<=n; i++)
		if(!dfn[i]) tarjan(i);
	for(auto it : edges)
	{
		int u = num[it.fi], v = num[it.se];
		if(u!=v) DAG[u].pb(v), deg[u]++, deg[v]++;
	}
	int lim = (int)sqrt(tot) + 1;
	iota(idx+1, idx+tot+1, 1);
	sort(idx+1, idx+tot+1, [](int x, int y) {
		return deg[x] > deg[y];
	});
	for(int i=1; i<=lim; i++) 
	{
		dfs(idx[i], i);
		spe[idx[i]] = i;
	}
}
bool dfs2(int s, int t, int tt)
{
	if(s==t) return 1;
	if(spe[s]) return bit[spe[s]].test(t);
	vis[s] = tt;
	for(int ss : DAG[s])
	{
		if(vis[ss]==tt) continue;
		if(dfs2(ss, t, tt)) return 1;
	}
	return 0;
}
void solve(int t)
{
	int u, v;
	scanf("%d%d", &u, &v);
	++u, ++v;
	if(num[u]==num[v]) puts("Good");
	else puts((dfs2(num[u], num[v], t) ? "Good" : "Bad"));
}
int main()
{
	scanf("%d%d", &n, &m);
	for(int i=1; i<=m; i++) 
	{
		int u, v;
		scanf("%d%d", &u, &v);
		++u, ++v;
		G[u].pb(v);
		edges.emplace_back(u, v);
	}
	prework();
	scanf("%d", &_);
	for(int i=1; i<=_; i++) solve(400+i);
	return 0;
}

上一题