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;
}

浙公网安备 33010602011771号