Codeforces 1270G Subset with Zero Sum

Codeforces 1270G Subset with Zero Sum

https://codeforces.com/contest/1270/problem/G

长度为 \(n\) 的正整数序列 \(a_1,a_2,\cdots,a_n\) , 满足

\[i - n \le a_i \le i - 1 \]

请找出一个非空子序列满足和为 \(0\) .

可以证明总是存在合法方案.

\(T\) 组数据.

\(1 \le T \le 10^6\)

\(1 \le n \le 10^6, \sum n \le 10^6\)

Tutorial

将不等式变形

\[1 \le i -a_i \le n \]

可以建立一张 \(n\) 个点的有向图,从 \(i\)\(i-a_i\) 连边.

那么图中一定存在一个有向环,找到任意一个这样的环,设其中的点为 \(u_1,u_2,\cdots,u_k\) ,则有

\[u_1-a_{u_1}=u_2 \\ u_2-a_{u_2}=u_3 \\ \cdots \\ u_k-a_{u_k}=u_1 \]

所以可以得到 \(a_{u_1}+a_{u_2}+\cdots+a_{u_k}=0\) .

复杂度 \(O(n)\)

Code

#include <cassert>
#include <cstdio>
#include <iostream>
#include <vector>
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
inline char nc()
{
//	return getchar();
	static char buf[100000],*l=buf,*r=buf;
	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++;
}
template<class T> void read(T &x)
{
	x=0; int f=1,ch=nc();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=nc();}
	x*=f;
}
typedef long long ll;
const int maxn=1e6+50;
int n;
int T;
int a[maxn];
bool vis[maxn];
vector<int> R;
vector<int> an;
void dfs(int u)
{
	if(vis[u]) return; vis[u]=1;
	R.push_back(u);
	dfs(u-a[u]);
}
int main()
{
	read(T);
	for(int kase=1;kase<=T;++kase)
	{
		read(n);
		for(int i=1;i<=n;++i)
		{
			read(a[i]);
		}
		dfs(1);
		ll sum=0;
		for(int i=R.size()-1;~i;--i)
		{
			sum+=a[R[i]]; an.push_back(R[i]);
			if(sum==0) break;
		}
		printf("%d\n",(int)an.size());
		for(int i=0;i<an.size();++i)
		{
			if(i) printf(" ");
			printf("%d",an[i]);
		}
		printf("\n");
		R.clear();
		an.clear();
		for(int i=1;i<=n;++i) vis[i]=0;
	}
	return 0;
}
posted @ 2020-05-29 20:43  LJZ_C  阅读(164)  评论(0编辑  收藏  举报