[国家集训队]稳定婚姻

嘟嘟嘟

这道题一看就知道是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 }
View Code

猜你喜欢

转载自www.cnblogs.com/mrclr/p/9861056.html