1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
  | // 더 많은 정보는 42jerrykim.github.io 에서 확인하세요.
#include <bits/stdc++.h>
using namespace std;
static const int MAXN = 5005;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n; if(!(cin >> n)) return 0;
    vector<bitset<MAXN>> adj(n);
    for(int i=0;i<n;++i){
        int k; cin >> k;
        for(int t=0;t<k;++t){
            int a; cin >> a; int j = a-1;
            if(j<0||j>=n||j==i) continue;
            adj[i].set(j);
            adj[j].set(i);
        }
    }
    vector<int> degree(n);
    for(int i=0;i<n;++i) degree[i] = (int)adj[i].count();
    vector<int> order(n); iota(order.begin(), order.end(), 0);
    sort(order.begin(), order.end(), [&](int a, int b){
        if(degree[a] != degree[b]) return degree[a] > degree[b];
        return a < b;
    });
    vector<int> ds(n+1,0);
    for(int i=1;i<=n;++i) ds[i] = degree[order[i-1]];
    int k = 0; for(int i=1;i<=n;++i) if(ds[i] >= i-1) k = i;
    long long sumTop = 0, rhs = 1LL*k*(k-1);
    for(int i=1;i<=k;++i) sumTop += ds[i];
    for(int i=k+1;i<=n;++i) rhs += min(ds[i], k);
    if(sumTop != rhs){ cout << 0 << '\n'; return 0; }
    vector<int> Klist, Slist; Klist.reserve(k); Slist.reserve(n-k);
    vector<char> inK(n, 0);
    for(int i=0;i<k;++i){ inK[order[i]] = 1; Klist.push_back(order[i]); }
    for(int i=k;i<n;++i) Slist.push_back(order[i]);
    int Ksize = (int)Klist.size();
    int Ssize = (int)Slist.size();
    long long answer = 0;
    if(Ksize>0 && Ssize>0) answer += 1; // 기준 분할
    // K -> S 단일 이동 후보 카운트
    vector<int> sNeighborCount(n, 0);
    vector<int> soleSNeighbor(n, -1);
    vector<int> countXSingles(n, 0);
    int Xcount = 0; // x in K with zero neighbors in S
    for(int x: Klist){
        int cnt = 0, yfound = -1;
        for(int y: Slist){
            if(adj[x].test(y)){
                ++cnt;
                if(cnt==1) yfound = y; else break;
            }
        }
        sNeighborCount[x] = cnt;
        if(cnt==0) ++Xcount;
        else if(cnt==1){ soleSNeighbor[x] = yfound; ++countXSingles[yfound]; }
    }
    // S -> K 단일 이동 후보 카운트
    vector<int> nonNeighborKCount(n, 2);
    vector<int> soleKNonNeighbor(n, -1);
    int Ycount = 0; // y in S adjacent to all K
    for(int y: Slist){
        int cnt = 0, xnon = -1;
        for(int x: Klist){
            if(!adj[y].test(x)){
                ++cnt; if(cnt==1) xnon = x; else break;
            }
        }
        if(cnt==0){ nonNeighborKCount[y]=0; ++Ycount; }
        else if(cnt==1){ nonNeighborKCount[y]=1; soleKNonNeighbor[y]=xnon; }
        else nonNeighborKCount[y]=2;
    }
    if(Ksize>=2) answer += Xcount;
    if(Ssize>=2) answer += Ycount;
    long long pairs = 0;
    for(int y: Slist){
        int nk = nonNeighborKCount[y];
        if(nk==0){
            pairs += Xcount; // x with 0 S-neighbors
            pairs += countXSingles[y]; // x whose sole S-neighbor is y
        }else if(nk==1){
            int x0 = soleKNonNeighbor[y];
            if(sNeighborCount[x0]==0) ++pairs;
            else if(sNeighborCount[x0]==1 && soleSNeighbor[x0]==y) ++pairs;
        }
    }
    answer += pairs;
    cout << answer << '\n';
    return 0;
}
  |