CodeForces 1270G Subset with Zero Sum

题目传送门

我们先转化一下条件,变为 \(1\le i-a_i\le n\)

然后有一步非常妙的转化,连边 \(i\rightarrow i-a_i\)

我们不难发现这是一棵基环树(森林),那么图中显然存在环,注意到对于一个环,有 \(i=i-\sum a_j\),即 \(\sum a_j=0\),于是我们找到环就构造完了。

AC code:

#include<bits/stdc++.h>
#define int long long
#define N 1000005
#define pii pair<int,int>
#define x first
#define y second
#define mod 1000000000
#define inf 2e18
using namespace std;
int T=1,n,a[N],d[N];
vector<int>e[N];
void add(int a,int b){
	e[a].push_back(b);
	d[b]++;
}
void solve(int cs){
	cin>>n;
	for(int i=1;i<=n;i++){
		e[i].clear();
		d[i]=0;
	}
	for(int i=1;i<=n;i++){
		cin>>a[i];
		add(i,i-a[i]);
	}
	queue<int>q;
	for(int i=1;i<=n;i++){
		if(!d[i]){
			q.push(i);
		}
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(auto j:e[u]){
			if(!--d[j])q.push(j);
		}
	}
	int beg=0;
	for(int i=1;i<=n;i++){
		if(d[i]){
			beg=i;
			break;
		}
	}
	int cur=beg;
	vector<int>res;
	do{
		cur=e[cur][0];
		res.push_back(cur);
	}while(cur!=beg);
	cout<<res.size()<<'\n';
	for(auto it:res){
		cout<<it<<' ';
	}
	cout<<'\n';
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>T;
//	init();
	for(int cs=1;cs<=T;cs++){
		solve(cs);
	}
	return 0;
}
posted @ 2025-04-30 19:51  zxh923  阅读(14)  评论(0)    收藏  举报