把所有同方向的箭头连起来成一条链,可以发现,位于同一链的点不共存
a->b->c<-d
每次选择位于一条链之中的点,可以保证影响范围只有一条链,如b
但是如果是两端就会影响两条链,如a,c,d
依次向前后传递的状态可以用递归解决
应该不能用二维数组储存图吧,数据量太大。。。
分享一篇题解:https://www.luogu.org/problemnew/solution/CF353E
试图用邻接表,时间复杂度O(n ^5)TLE:
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <cstring>
#include <stdio.h>
#include <algorithm>
#include <vector>
#define MAX 100010
using namespace std;
char a[MAX];
int n;
int mark[MAX];
vector<int> g[MAX];
struct node {
int id,num;
}cnt[MAX];
int que[MAX];
int top_que;
int check(int x){ //判断是否可达
for(int i=0;i<top_que;i++){
int s=que[i];
int lens=g[s].size();
int lenx=g[x].size();
for(int j=0;j<lens;j++){
if(g[s][j]==x)
return 0; //可达返回0
}
for(int j=0;j<lenx;j++){
if(g[x][j]==s)
return 0;
}
}
return 1; //不可达返回1
}
void update(){ //更新数据
for(int i=0;i<n;i++){
if(!mark[i]&&!check(i)){
mark[i]=1;
}
}
}
int afind(int y,int x){
int leny=g[y].size();
for(int i=0;i<leny;i++){
if(g[y][i]==x)
return 1;
}
return 0;
}
int main()
{
while(~scanf("%s",a)){
n=strlen(a);
memset(cnt,0,sizeof(cnt));
memset(g,0,sizeof(g));
top_que=0;
for(int i=0;i<n;i++){
int j=(i+1)%n;
cnt[i].id=i;
cnt[i].num++;
cnt[j].num++;
if(a[i]=='0'){
g[i].push_back(j);
}
else {
g[j].push_back(i);
}
}
// for(int i=0;i<n;i++){
// int leni=g[i].size();
// printf("%d:",i);
// for(int j=0;j<leni;j++){
// printf("%d ",g[i][j]);
// }
// printf("\n");
// }
for(int o=0;o<n;o++){
for(int i=0;i<n;i++){
int leni=g[i].size();
for(int j=0;j<leni;j++){
int y=g[i][j];
int leny=g[y].size();
for(int k=0;k<leny;k++){
if(!afind(i,g[y][k])){
g[i].push_back(g[y][k]);
cnt[i].num++;
cnt[g[y][k]].num++;
}
}
}
}
}
// for(int i=0;i<n;i++){
// int leni=g[i].size();
// printf("%d:",i);
// for(int j=0;j<leni;j++){
// printf("%d ",g[i][j]);
// }
// printf("\n");
// }
memset(mark,0,sizeof(mark));
for(int i=0;i<n;i++){ //先筛选在一条链之中的点
int j=(i+1)%n;
if(a[i]==a[j]&&!mark[j]){
mark[j]=1;
que[top_que++]=j;
update();
}
}
for(int i=0;i<n;i++){
if(!mark[i]){ //再筛选一条链两端的点
mark[i]=1;
que[top_que++]=i;
update();
}
}
printf("%d\n",top_que);
}
return 0;
}