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 }
View Code

本人代码 (只判了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 }
View Code

 

posted @ 2020-10-09 23:42  古比  阅读(160)  评论(0编辑  收藏  举报