http://acm.hdu.edu.cn/showproblem.php?pid=5961php
咱们称一个有向图G是传递的,当且仅当对任意三个不一样的顶点a,,若G中有 一条边从a到b且有一条边从b到c ,则G中一样有一条边从a到c。
咱们称图G是一个竞赛图,当且仅当它是一个有向图且它的基图是彻底图。换句 话说,将彻底图每条边定向将获得一个竞赛图。
下图展现的是一个有4个顶点的竞赛图。c++
如今,给你两个有向图P = (V,Ep)和Q = (V,Ee),知足:测试
包含至多20组测试数据。
第一行有一个正整数,表示数据的组数。
对于每组数据,第一行有一个正整数n。接下来n行,每行为连续的n个字符,每 个字符只多是’-’,’P’,’Q’中的一种。
∙若是第i行的第j个字符为’P’,表示有向图P中有一条边从i到j;
∙若是第i行的第j个字符为’Q’,表示有向图Q中有一条边从i到j;
∙不然表示两个图中均没有边从i到j。
保证1 <= n <= 2016,一个测试点中的多组数据中的n的和不超过16000。保证输入的图必定知足给出的限制条件。spa
对每一个数据,你须要输出一行。若是P! Q都是传递的,那么请输出’T’。不然, 请输出’N’ (均不包括引号)。code
4
4
-PPP
--PQ
---Q
----
4
-P-P
--PQ
P--Q
----
4
-PPP
--QQ
----
--Q-
4
-PPP
--PQ
----
--Q-ip
T
N
T
Nci
题目给了贼多的条件,感受好像是很难的问题。get
因而咱们随机化吧,随便随机了一下就过了。input
#include<bits/stdc++.h> using namespace std; const int maxn = 2017; string s[maxn]; vector<int> E1[maxn]; vector<int> E2[maxn]; int n; int step; int check1(){ step = 1000000; for(int i=0;i<step;i++){ int x = rand()%n+1; for(int j=0;j<E1[x].size();j++){ int v = E1[x][j]; for(int k=0;k<E1[v].size();k++){ int z = E1[v][k]; if(s[x][z]!='P') return 0; step--; if(step<i)return 1; } } } return 1; } int check2(){ step = 1000000; for(int i=0;i<step;i++){ int x = rand()%n+1; for(int j=0;j<E2[x].size();j++){ int v = E2[x][j]; for(int k=0;k<E2[v].size();k++){ int z = E2[v][k]; if(s[x][z]!='Q') return 0; step--; if(step<i)return 1; } } } return 1; } void solve(){ scanf("%d",&n); for(int i=0;i<maxn;i++) E1[i].clear(),E2[i].clear(); for(int i=0;i<n;i++) cin>>s[i]; for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(s[i][j]=='P'){ E1[i].push_back(j); } } } int flag1=check1(); for(int i=0;i<maxn;i++) E1[i].clear(),E2[i].clear(); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ if(s[i][j]=='Q'){ E2[i].push_back(j); } } } int flag2=check2(); if(flag1+flag2==2){ cout<<"T"<<endl; }else{ cout<<"N"<<endl; } } int main(){ srand(772002); int t;scanf("%d",&t); while(t--)solve(); }