zoukankan      html  css  js  c++  java
  • [国家集训队]稳定婚姻

    嘟嘟嘟

    这道题一看就知道是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
  • 相关阅读:
    Shiro入门学习之shi.ini实现授权(三)
    Shiro入门学习之shi.ini实现认证及源码分析(二)
    猜字母游戏(Java)
    二维数组的语法
    鸡兔同笼问题(Java)
    成绩统计程序(Java)
    18位身份证验证(Java)加入身份证输入验证是否满足18位代码(修订稿)
    18位身份证验证(Java)
    键盘输入字符插入定义数组中并按顺序排列
    一个随机验证码且不重复的小程序以及求随机输入一组数组中的最大值(Java)
  • 原文地址:https://www.cnblogs.com/mrclr/p/9861056.html
Copyright © 2011-2022 走看看