竞赛图的性质
a -> b b -> c 则 a ->c
多画几个样例就可以总结出了 edge[a] & edge[b] = edge[b]
a连得边的集合 交上 b连的边的集合 = b连得边的集合。
处理集合的交集就用bitset就好了。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2022;
const int maxm = maxn*maxn;
#define mem(a,x) memset(a,x,sizeof a)
struct node{
int v,next;
}edge[maxm];
int head[maxn] ,cnt;
int n;
char mp[maxn][maxn];
bitset<maxn>b[maxn];
void add_edge(int u,int v){
edge[cnt].v = v, edge[cnt].next = head[u];
head[u] = cnt++;
b[u][v] = 1;
}
bool legal(char ch){
mem(head,-1);
cnt = 0;
for(int i=1;i<=n;i++) b[i].reset();
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(mp[i][j] == ch){
add_edge(i,j);
}
}
}
for(int i=1;i<=n;i++){
for(int j=head[i];j+1;j = edge[j].next){
int v = edge[j].v;
if((b[i] & b[v] )!= b[v]) return 0;
}
}
return 1;
}
int main(){
int t;scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",mp[i] + 1);
}
if(legal('P') && legal('Q')){
printf("T\n");
}
else
printf("N\n");
}
return 0;
}
暴力求解。。
#include<bits/stdc++.h>
using namespace std;
const int N = 2020;
vector<int>G[N]; int n;
char str[N][N];
bool legal(char ch){
for(int i=0;i<n;i++){
for(int j=0;j<G[i].size();j++){
int v = G[i][j];
for(int k=0;k<G[v].size();k++){
int v2 = G[v][k];
if(str[i][v2] != ch) {
return 0;
}
}
}
}
return 1;
}
int main(){
int t;scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=0;i<=n;i++)G[i].clear();
for(int i=0;i<n;i++){
scanf("%s",str[i]);
for(int j=0;j<n;j++){
if(str[i][j] == 'P')
G[i].push_back(j);
}
}
if(!legal('P')){
// cout<<"bb"<<endl;
printf("N\n");continue;
}
for(int i=0;i<=n;i++)G[i].clear();
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(str[i][j] == 'Q')
G[i].push_back(j);
}
}
if(!legal('Q')){
printf("N\n");continue;
}
else
printf("T\n");
}
return 0;
}