【四校联考】传递
【题解】
如果一个图是竞赛图那么如果存在边<a,b>,那么a一定能走到b,反之亦然
还有,如果在图P中存在边<a,b>,那么图Q中一定不存在边<a,b>或<b,a>(基图是完全图)
那么,如果图P中存在边<a,b>,图Q一定不能从a走到b或者从b走到a
既然如此,因为图P+图Q是完全图
所以,对于点u和点v,u和v之间的边要不然在P里,要不然在Q里,
所以要不然只能从u走到v,要不然只能从v走到u,
那么,这不就是一个DAG嘛
于是我们把Q里的边分别正着反着加入P
判断是不是DAG即可
#include<stdio.h> #include<stdlib.h> #include<iostream> #include<string> #include<string.h> #include<algorithm> #include<math.h> #include<queue> #include<map> #include<vector> #include<set> #define il inline #define re register using namespace std; const int N=3001; int n,in[N],T; bool s[N][N],p[N][N],q[N][N],d[N][N]; queue<int> que; il bool chk(){ memset(in,false,sizeof(in)); for(re int i=1;i<=n;i++){ for(re int j=1;j<=n;j++) in[j]+=d[i][j]; } for(int i=1;i<=n;i++) if(!in[i]) que.push(i); while(!que.empty()){ re int h=que.front();que.pop(); for(re int i=1;i<=n;i++) if(d[h][i]){ in[i]--; if(!in[i]){ que.push(i); } } } for(int i=1;i<=n;i++){ if(in[i]) return false; } return true; } il void init(){ memset(p,false,sizeof(p)); memset(q,false,sizeof(q)); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",s[i]+1); for(int j=1;j<=n;j++){ if(s[i][j]=='P') p[i][j]=1; else if(s[i][j]=='Q') q[i][j]=1; } } memset(d,false,sizeof(d)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ if(p[i][j]) d[i][j]=1; if(q[i][j]) d[i][j]=1; } if(!chk()){ printf("N\n");return; } memset(d,false,sizeof(d)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ if(p[i][j]) d[i][j]=1; if(q[i][j]) d[j][i]=1; } if(!chk()){ printf("N\n");return; } printf("T\n"); } int main(){ freopen("trans.in","r",stdin); freopen("trans.out","w",stdout); scanf("%d",&T); for(int i=1;i<=T;i++) init(); return 0; }
蜉蝣渴望着飞翔,尽管黄昏将至