A - 传递 拓扑排序
链接:https://vjudge.net/contest/400079#problem/A
思路:
题目已经给出如何判断一个图是传递的.
当这个图为传递的,两个子图要满足两个条件:
- P+Q的合图无环
- P+Q的反图(即Q图重的方向改成反向)的合图无环
使用拓扑排序判环即可
他人代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define mem(a, b) memset(a, b, sizeof(a)) 4 const int N = 2020; 5 vector<int> e1[N]; 6 vector<int> e2[N]; 7 char s[N][N]; 8 int vis[N], n; 9 bool dfs1(int u) 10 { 11 vis[u] = -1; 12 for (auto v : e1[u]) 13 { 14 if (vis[v] < 0) 15 return false; 16 else if (!vis[v] && !dfs1(v)) 17 return false; 18 } 19 vis[u] = 1; 20 return true; 21 } 22 bool dfs2(int u) 23 { 24 vis[u] = -1; 25 for (auto v : e2[u]) 26 { 27 if (vis[v] < 0) 28 return false; 29 else if (!vis[v] && !dfs2(v)) 30 return false; 31 } 32 vis[u] = 1; 33 34 return true; 35 } 36 bool topsort1() 37 { 38 39 mem(vis, 0); 40 for (int u = 1; u <= n; u++) 41 if (!vis[u]) 42 if (!dfs1(u)) 43 return false; 44 return true; 45 } 46 bool topsort2() 47 { 48 49 mem(vis, 0); 50 for (int u = 1; u <= n; u++) 51 if (!vis[u]) 52 if (!dfs2(u)) 53 return false; 54 return true; 55 } 56 void solve() 57 { 58 scanf("%d", &n); 59 for (int i = 1; i <= n; i++) 60 { 61 e1[i].clear(); 62 e2[i].clear(); 63 } 64 for (int i = 1; i <= n; i++) 65 { 66 scanf("%s", s[i] + 1); 67 for (int j = 1; j <= n; j++) 68 { 69 if (s[i][j] == 'P') 70 { 71 //puts("!!!"); 72 e1[i].push_back(j); 73 e2[i].push_back(j); 74 } 75 else if (s[i][j] == 'Q') 76 { 77 e1[i].push_back(j); 78 e2[j].push_back(i); 79 } 80 } 81 } 82 int f1 = topsort1(), f2 = topsort2(); 83 if (topsort1() && topsort2()) 84 puts("T"); 85 else 86 puts("N"); 87 } 88 int main() 89 { 90 // freopen("in.txt", "r", stdin); 91 int t; 92 scanf("%d", &t); 93 while (t--) 94 solve(); 95 return 0; 96 }
本人代码 (只判了P+Q的返图,但也能ac)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=2100; 4 char a[maxn][maxn]; 5 struct node 6 { 7 int v,nxt; 8 }G[maxn*maxn]; 9 int head[maxn];int num; 10 int in[maxn]; 11 void add(int u,int v) 12 { 13 G[++num].v=v;G[num].nxt=head[u];head[u]=num; 14 } 15 void init() 16 { 17 memset(head,0,sizeof(head)); 18 num=0; 19 memset(in,0,sizeof(in)); 20 21 } 22 int tuopu(int n) 23 { 24 int num=0; 25 queue<int>q; 26 for(int i=1;i<=n;i++){ 27 if(!in[i]){ 28 q.push(i); 29 num++; 30 } 31 } 32 while(!q.empty()){ 33 int u=q.front(); 34 q.pop(); 35 for(int i=head[u];i;i=G[i].nxt){ 36 int v=G[i].v; 37 in[v]--; 38 if(!in[v]){ 39 q.push(v); 40 num++; 41 } 42 } 43 } 44 if(num==n) return 1; 45 else return 0; 46 } 47 int main() 48 { 49 int T; 50 scanf("%d",&T); 51 while(T--){ 52 init(); 53 int n; 54 scanf("%d",&n); 55 for(int i=1;i<=n;i++){ 56 scanf("%s",a[i]+1); 57 } 58 for(int i=1;i<=n;i++){ 59 for(int j=1;j<=n;j++){ 60 if(a[i][j]=='P'){ 61 add(i,j); 62 in[j]++; 63 } 64 if(a[i][j]=='Q'){ 65 add(j,i); 66 in[i]++; 67 } 68 } 69 } 70 if(tuopu(n)){ 71 printf("T\n"); 72 } 73 else printf("N\n"); 74 } 75 return 0; 76 }