传递 Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)我们称图G是一个竞赛图,当且仅当它是一个有向图且它的基图是完全图。换句 话说,将完全图每条边定向将得到一个竞赛图。 下图展示的是一个有4个顶点的竞赛图。 ![]() 现在,给你两个有向图P = (V,E 1. E 2. (V,E 你的任务是:判定是否P,Q同时为传递的。 第一行有一个正整数,表示数据的组数。 对于每组数据,第一行有一个正整数n。接下来n行,每行为连续的n个字符,每 个字符只可能是’-’,’P’,’Q’中的一种。 ∙ ∙ ∙ 保证1 <= n <= 2016,一个测试点中的多组数据中的n的和不超过16000。保证输入的图一定满足给出的限制条件。 |
如果u是v的父节点,v是w的父节点,那么u一定也是w的父节点,用bitset记录每个点的父节点有哪些,跑一遍spfa,最后枚举每个点的父节点看是否与父节点连上了一条边
#include<bits/stdc++.h>
using namespace std;
const int MX = 2020;
char mp[MX][MX];
bitset<MX>b[MX];
struct Edge {int v, nxt;
} E[MX*MX], edge[MX*MX];
int head[MX], Head[MX], tot, rear, n;
int p[MX], p1[MX], p2[MX], vis[MX];
void init() {memset(head, -1, sizeof(head));memset(Head, -1, sizeof(Head));for (int i = 0; i < n; i++) p1[i] = p2[i] = i;tot = rear = 0;
}
void ADD(int u, int v) {E[tot].v = v;E[tot].nxt = Head[u];Head[u] = tot++;
}
void add(int u, int v) {edge[rear].v = v;edge[rear].nxt = head[u];head[u] = rear++;
}
int find(int x) {return p[x] == x ? x : (p[x] = find(p[x]));
}
int find1(int x) {return p1[x] == x ? x : (p1[x] = find1(p1[x]));
}
int find2(int x) {return p2[x] == x ? x : (p2[x] = find2(p2[x]));
}
bool solve(Edge E[], int head[], int px[], char op) {for (int i = 0; i < n; i++) {b[i].reset();b[i][i]=1;vis[i] = 0;p[i] = px[i];}queue<int>q;for (int i = 0; i < n; i++) if (find(i) == i) {q.push(i); vis[i] = 1;}while (!q.empty()) {int u = q.front(); q.pop();vis[u] = 0;for (int i = head[u]; ~i; i = E[i].nxt) {int v = E[i].v;if ((b[v] | b[u]) != b[v]) {b[v] |= b[u];if (!vis[v]) {q.push(v);vis[v] = 1;}}}}for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if (i == j) continue;if (b[i][j] && mp[j][i] != op) return false;}}return true;
}
int main() {int T;//freopen("in.txt","r",stdin);scanf("%d", &T);while (T--) {scanf("%d", &n);init();for (int i = 0; i < n; i++) scanf("%s", &mp[i]);for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if (mp[i][j] == 'P') {ADD(i, j);int pi = find1(i), pj = find1(j);if (pi != pj) p1[pj] = pi;}if (mp[i][j] == 'Q') {add(i, j);int pi = find2(i), pj = find2(j);if (pi != pj) p2[pj] = pi;}}}if (solve(E, Head, p1, 'P') && solve(edge, head, p2, 'Q')) printf("T\n");else printf("N\n");}return 0;
}