题意:给你一个有向图,满足去掉方向是完全图,将其拆成PQ两个图(没有公共边),问你两图是否分别满足对于任意3个点a,b,c 若有一条边从a到b且有一条边从b到c ,则同样有一条边从a到c。
题解:观察,发现题目等价于对PQ分别bfs。如果某点的深度大于等于2就判错。用vis储存深度,注意对vis数组的操作:每推入一个起点时,vis[起点]=1,(pop时不--,最后统一memset0)每推入一个未访问的相邻点v时vis[v]=vis[now]+1;
坑:1.cin>>n写错地方,结果写了两个cin>>n,结果把图的第一个符吞了。2.q.clear没有这个函数,用赋值 q1 = queue<int>();3.用邻接链表建图遍历边时循环从0开始
ac代码:
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<stdio.h> #include<vector> #include<algorithm> #include<vector> #include<queue> #include<string.h> using namespace std; const int maxn = 2020; vector<int> EP[maxn],EQ[maxn]; char map[maxn][maxn]; int vis[maxn]; int main() { int t; cin >> t; while (t--) { int n; cin >> n; for (int i = 1; i <= n; i++) { EP[i].clear(); EQ[i].clear(); } for (int i = 1; i <= n; i++) { scanf("%s", map[i]+1); //cout << map[i] << endl; for (int j =1; j < n; j++) { if (map[i][j] == 'P')EP[i].push_back(j); if (map[i][j] == 'Q') EQ[i].push_back(j); } } //for (int i = 1; i <= n; i++)cout << map[i]<<endl; //bfs(); int flag = 1; queue<int> Q; for (int i = 1; i <= n; i++) { if (EP[i].empty()) continue; memset(vis, 0, sizeof(vis)); Q.push(i); vis[i] = 1; while (!Q.empty()) { int now = Q.front(); Q.pop(); //vis[now]--; for (int j = 0; j < EP[now].size(); j++) { int v = EP[now][j]; if (!vis[v]) { vis[v]=vis[now]+1; Q.push(v); } if (vis[v] == 3) { flag = 0; break; } } } if (flag == 0)break; } if (!flag) { puts("N"); continue; } //repeat; flag = 1; while (!Q.empty()) Q.pop(); for (int i = 1; i <= n; i++) { if (EQ[i].empty()) continue; memset(vis, 0, sizeof(vis)); Q.push(i); vis[i] = 1; while (!Q.empty()) { int now = Q.front(); Q.pop(); //vis[now]--; for (int j = 0; j < EQ[now].size(); j++) { int v = EQ[now][j]; if (!vis[v]) { vis[v] = vis[now] + 1; Q.push(v); } if (vis[v] == 3) { flag = 0; break; } } } if (flag == 0)break; } if (!flag) puts("N"); else puts("T"); } }