题目链接
题意:给定n个字符串,你可以选择任意字符串进行反转,存在一种方案能使的n个字符串首尾相连的最小反转次数。
思路:统计四种情况,1、首0尾1 ; 2、首1尾0;3、首0尾0;4、首1尾1。首先情况3和4翻不翻转对结果无影响,我们只考虑情况1和2,要先字符串首尾相接,情况1和清空2的数量之差肯定为0或1(这个可以自己验证)。然后用map记录一下重复字符串,进行模拟即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+1;
map<string,bool>vis;
vector<int>ans;
string str[maxn],s;
int main()
{
int T,n,a,b,c,d,f[maxn];
scanf("%d",&T);
while(T--)
{
a=b=c=d=0;
vis.clear();ans.clear();
scanf("%d",&n);
for(int i=1;i<=n;++i) f[i]=0;
for(int i=1;i<=n;++i)
{
cin>>s;
str[i]=s;vis[s]=1;
int t=(s[0]-'0')*10+(s[s.size()-1]-'0');
if(t==1) a++,f[i]=1;
if(t==10) b++,f[i]=-1;
if(t==0) c++;
if(t==11) d++;
}
if(!a&&!b&&c&&d){
puts("-1");continue;
}
int cnt=a-b;
if(cnt>1)
{
for(int i=1;i<=n;++i)
{
if(f[i]==1)
{
s=str[i];
reverse(s.begin(),s.end());
if(!vis[s]) vis[s]=1,cnt-=2,ans.push_back(i);
}
if(cnt<=1) break;
}
}
else if(cnt<-1) {
for(int i=1;i<=n;++i)
{
if(f[i]==-1)
{
s=str[i];
reverse(s.begin(),s.end());
if(!vis[s]) vis[s]=1,cnt+=2,ans.push_back(i);
}
if(cnt>=-1) break;
}
}
if(cnt>1||cnt<-1) puts("-1");
else if(cnt<=1&&cnt>=-1) {
printf("%d\n",ans.size());
for(int i=0;i<ans.size();++i) printf("%d%s",ans[i],(i==ans.size()-1)?"\n":" ");
}
}
}