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(); }