1. 程式人生 > >hdu5961傳遞(bitset亂搞)

hdu5961傳遞(bitset亂搞)

題目連結:

題意:

中文題

題解:

1、判斷傳遞的條件為:若G中有 一條邊從a到b且有一條邊從b到c ,則G中同樣有一條邊從a到c。
2、我們去列舉b,我們假設集合Sb={x|x>b}表示有一條x指向b的邊。我們假設集合Tb={x|b>x},表示有有一條b指向x的邊。
3、我們再去列舉Sb中的元素,假設我們當前列舉的是x,因為x是指向b的,所以我們根據題意容易得知該圖是傳遞圖的話一定滿足:TxTb=Tb,然後就可以得出答案了,至於怎麼處理集合的並,我們可以用bitset搞搞就可以了!!!具體看程式碼。

程式碼:

#include<cstdio>
#include<cstring> #include<iostream> #include<sstream> #include<algorithm> #include<vector> #include<bitset> #include<set> #include<queue> #include<stack> #include<map> #include<cstdlib> #include<cmath> #define PI 2*asin(1.0) #define LL long long
#define pb push_back #define pa pair<int,int> #define clr(a,b) memset(a,b,sizeof(a)) #define lson lr<<1,l,mid #define rson lr<<1|1,mid+1,r #define bug(x) printf("%d++++++++++++++++++++%d\n",x,x) #define key_value ch[ch[root][1]][0] const int MOD = 1000000007; const int N = 2016+15; const int
maxn = 200+ 14; const int mm=100010; const int letter = 130; const int INF = 1e9; const double pi=acos(-1.0); const double eps=1e-8; using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int T,n; char s[N][N]; bitset<N>vs[2][N],tt; int main(){ scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%s",s[i]+1); for(int i=1;i<=n;i++) vs[0][i].reset(),vs[1][i].reset(); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(s[i][j]=='P'){ vs[1][i][j]=vs[0][j][i]=1; } } } int flag=1; for(int x=1;x<=n;x++){ for(int i=1;i<=n;i++){ if(vs[0][x][i]){ tt=vs[1][i]&vs[1][x]; if(tt!=vs[1][x]){flag=0;break;} } } if(!flag) break; } if(!flag){ puts("N"); continue; } for(int i=1;i<=n;i++) vs[0][i].reset(),vs[1][i].reset(); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(s[i][j]=='Q'){ vs[1][i][j]=vs[0][j][i]=1; } } } flag=1; for(int x=1;x<=n;x++){ for(int i=1;i<=n;i++){ if(vs[0][x][i]){ tt=vs[1][i]&vs[1][x]; if(tt!=vs[1][x]){flag=0;break;} } } if(!flag) break; } if(flag) puts("T"); else puts("N"); } return 0; }