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;
}
|