这道题一看就知道是tarjan。
刚开始我是建无向图,然后边双缩点,判断夫妻是否在一个边双连通分量中。但是这个算法是错的,我也不知道为啥,求助各路大佬。
正确的做法是给每一条边规定方向:夫妻边女->男,情侣边男->女。这样就保证了每一条路径一定是男->女->男->女。最后只用判断每一对夫妻是否在一个环中,即是否在一个强联通分量中。
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<queue> 10 #include<stack> 11 #include<map> 12 using namespace std; 13 #define enter puts("") 14 #define space putchar(' ') 15 #define Mem(a, x) memset(a, x, sizeof(a)) 16 #define rg register 17 typedef long long ll; 18 typedef double db; 19 const db eps = 1e-8; 20 const int INF = 0x3f3f3f3f; 21 const int maxn = 8e3 + 5; 22 const int maxe = 4e4 + 5; 23 inline ll read() 24 { 25 ll ans = 0; 26 char ch = getchar(), las = ' '; 27 while(!isdigit(ch)) las = ch, ch = getchar(); 28 while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); 29 if(las == '-') ans = -ans; 30 return ans; 31 } 32 inline void write(ll x) 33 { 34 if(x < 0) putchar('-'), x = -x; 35 if(x >= 10) write(x / 10); 36 putchar(x % 10 + '0'); 37 } 38 39 int n, m; 40 char c[10]; 41 map<string, int> mp; 42 int Cnt = 0; 43 struct Edges 44 { 45 int x, y; 46 }egs[maxe]; 47 struct Edge 48 { 49 int nxt, to; 50 }e[maxe << 1]; 51 int head[maxn], ecnt = -1; 52 void addEdge(int x, int y) 53 { 54 e[++ecnt] = (Edge){head[x], y}; 55 head[x] = ecnt; 56 } 57 58 int st[maxn], top = 0; 59 int dfn[maxn], low[maxn], cnt = 0; 60 bool in[maxn]; 61 int col[maxn], ccol = 0; 62 void tarjan(int now) 63 { 64 dfn[now] = low[now] = ++cnt; 65 st[++top] = now; in[now] = 1; 66 for(int i = head[now]; i != -1; i = e[i].nxt) 67 { 68 if(!dfn[e[i].to]) 69 { 70 tarjan(e[i].to); 71 low[now] = min(low[now], low[e[i].to]); 72 } 73 else if(in[e[i].to]) low[now] = min(low[now], dfn[e[i].to]); 74 } 75 if(dfn[now] == low[now]) 76 { 77 int x; ++ccol; 78 do 79 { 80 x = st[top--]; 81 col[x] = ccol; 82 in[x] = 0; 83 }while(x != now); 84 } 85 } 86 87 int main() 88 { 89 Mem(head, -1); 90 n = read(); 91 for(int i = 1; i <= n; ++i) 92 { 93 int x, y; 94 scanf("%s", c); 95 if(!mp[c]) mp[c] = ++Cnt; 96 x = mp[c]; 97 scanf("%s", c); 98 if(!mp[c]) mp[c] = ++Cnt; 99 y = mp[c]; 100 addEdge(x, y); 101 egs[i].x = x; egs[i].y = y; 102 } 103 m = read(); 104 for(int i = 1; i <= m; ++i) 105 { 106 scanf("%s", c); int x = mp[c]; 107 scanf("%s", c); int y = mp[c]; 108 addEdge(y, x); 109 } 110 for(int i = 1; i <= Cnt; ++i) if(!dfn[i]) tarjan(i); 111 for(int i = 1; i <= n; ++i) 112 { 113 if(col[egs[i].x] == col[egs[i].y]) puts("Unsafe"); 114 else puts("Safe"); 115 } 116 return 0; 117 }