UPD 2020.04.30:本题解被发现存在严重错误,已更正。
题目链接
https://codeforces.com/contest/1338/problem/E
题解
这题太神了……这才是 div1E 啊,比什么 nim 积意义下的离散对数之类的高明到不知道哪里去了
这篇题解主要复述一下官方题解并补充一下官方题解上省略的证明。所有证明都是蒟蒻口胡的,有问题敬请指出。
下面把题目保证不存在的那个 4 4 4 个点的子图称作 H H H,用四元组表示 H H H 时,默认最后一个点入度为 3 3 3;整张图的点集记作 V V V. 设一个点 u u u 的入点集合为 i n ( u ) in(u) in(u).
首先对这个图进行拓扑排序,每次删掉入度为
0
0
0 的点,则该点对答案的贡献是
(
614
n
+
1
)
(614n+1)
(614n+1) 乘以剩下的点数。不妨假设剩下的图非空,下面的内容都在剩下的图上进行。我们会发现:
引理 0 不存在入度为
0
0
0 的点时,整张图是强连通的。
证明 对其缩点后,大小超过
1
1
1 的 SCC 必定有三元环,而入度为
0
0
0 的 SCC 必定大小超过
1
1
1. 因此如果 SCC 个数超过
1
1
1,则取入度为
0
0
0 的 SCC 的一个三元环和其余的 SCC 中的一个点,会构成
H
H
H.
引理 1
∀
u
,
i
n
(
u
)
∪
{
u
}
\forall u, in(u)\cup \{u\}
∀u,in(u)∪{u} 无环。
证明 反证,如果有环的话环上的点构成一个大小至少为
3
3
3 的 SCC,必定存在三元环,和
u
u
u 点构成
H
H
H.
引理 2 任取一个点
X
X
X,我们可以把整张图划分为两部分
P
=
i
n
(
X
)
∪
{
X
}
,
Q
=
V
∖
P
P=in(X)\cup \{X\},Q=V\setminus P
P=in(X)∪{X},Q=V∖P,则存在
u
∈
Q
,
v
∈
P
u\in Q,v\in P
u∈Q,v∈P 满足
(
u
,
v
)
(u,v)
(u,v) 有边。
证明 由于整张图强连通,显然。
(题解在这里的做法是取度数最大的点作为
X
X
X,实际上是需要的,理由将在下面给出。)
任取一个满足引理 2 条件的点
v
v
v. 设
R
=
i
n
(
v
)
∩
Q
,
S
=
Q
∖
R
R=in(v)\cap Q,S=Q\setminus R
R=in(v)∩Q,S=Q∖R.
引理 3
∀
y
∈
S
,
z
∈
R
\forall y\in S,z\in R
∀y∈S,z∈R,
(
y
,
z
)
(y,z)
(y,z) 有边。
证明 反证,设
(
z
,
y
)
(z,y)
(z,y) 有边,则
(
v
,
X
,
z
,
y
)
(v,X,z,y)
(v,X,z,y) 四个点构成
H
H
H.
引理 4
S
S
S 无环,
R
R
R 无环。
证明 根据引理 1 得
R
R
R 无环;若
S
S
S 有环则和
R
R
R 中任何一点构成
H
H
H.
引理 5
P
P
P 无环,
Q
Q
Q 无环。
证明 根据引理 1 得
P
P
P 无环,由
S
,
R
S,R
S,R 分别无环且
S
,
R
S,R
S,R 之间连的边都由
S
S
S 指向
R
R
R 得到
Q
=
S
∪
R
Q=S\cup R
Q=S∪R 无环。
到这里,我们就知道我们把这张图划分成了两个部分,且两部分分别无环。
对两部分分别进行拓扑排序,并给他们标号为
P
i
,
Q
i
P_i,Q_i
Pi,Qi(现在把集合看成序列),不妨设
i
<
j
i\lt j
i<j 当且仅当存在边
(
P
i
,
P
j
)
(P_i,P_j)
(Pi,Pj),
Q
Q
Q 同理。
设
i
n
P
(
u
)
=
i
n
(
u
)
∩
P
,
i
n
Q
(
u
)
=
i
n
(
u
)
∩
Q
inP(u)=in(u)\cap P,inQ(u)=in(u)\cap Q
inP(u)=in(u)∩P,inQ(u)=in(u)∩Q.
引理 6a
∀
i
\forall i
∀i,
i
n
Q
(
P
i
)
inQ(P_i)
inQ(Pi) 为
Q
Q
Q 的一段后缀;
证明 反证,若存在
j
<
k
j\lt k
j<k 满足
(
P
i
,
Q
k
)
,
(
Q
j
,
P
i
)
(P_i,Q_k),(Q_j,P_i)
(Pi,Qk),(Qj,Pi). 注意到
P
P
P 的最后一个元素是
X
X
X,且
X
X
X 向
Q
Q
Q 中每个点都连了边。于是
(
P
i
,
Q
j
,
X
,
Q
k
)
(P_i,Q_j,X,Q_k)
(Pi,Qj,X,Qk) 构成
H
H
H.
那么不难发现,
∀
i
,
j
\forall i,j
∀i,j, 若
∣
i
n
Q
(
P
i
)
∣
=
∣
i
n
Q
(
P
j
)
∣
|inQ(P_i)|=|inQ(P_j)|
∣inQ(Pi)∣=∣inQ(Pj)∣ 则
i
n
Q
(
P
i
)
=
i
n
Q
(
P
j
)
inQ(P_i)=inQ(P_j)
inQ(Pi)=inQ(Pj),否则大的包含小的。
引理 6b
∀
i
\forall i
∀i,
i
n
P
(
Q
i
)
inP(Q_i)
inP(Qi) 为
P
P
P 的一段后缀。
证明 设
l
i
l_i
li 为最小的
j
j
j 满足
(
Q
j
,
P
i
)
(Q_j,P_i)
(Qj,Pi) 有边(若不存在视为
+
∞
+\infty
+∞),可以证明
l
i
≤
l
i
+
1
l_i\le l_{i+1}
li≤li+1.
反证:若
l
i
>
l
i
+
1
l_i\gt l_{i+1}
li>li+1 且都不为
+
∞
+\infty
+∞,则
(
P
i
,
Q
l
i
+
1
,
Q
l
i
,
P
i
+
1
)
(P_i,Q_{l_{i+1}},Q_{l_i},P_{i+1})
(Pi,Qli+1,Qli,Pi+1) 四个点构成
H
H
H.
若
l
i
=
+
∞
l_i=+\infty
li=+∞,则由于入度不为
0
0
0,
P
1
P_1
P1 一定满足
l
1
≠
+
∞
l_1\ne +\infty
l1=+∞,即
(
Q
∣
Q
∣
,
P
1
)
(Q_{|Q|},P_1)
(Q∣Q∣,P1). 而因为
(
P
i
,
Q
∣
Q
∣
)
,
(
Q
∣
Q
∣
,
P
i
+
1
)
(P_i,Q_{|Q|}),(Q_{|Q|},P_{i+1})
(Pi,Q∣Q∣),(Q∣Q∣,Pi+1) 故
(
P
1
,
P
i
,
Q
∣
Q
∣
,
P
i
+
1
)
(P_1,P_i,Q_{|Q|},P_{i+1})
(P1,Pi,Q∣Q∣,Pi+1) 构成
H
H
H.
还有一个问题: d i s ( Q j , P i ) dis(Q_j,P_i) dis(Qj,Pi) 在 ( P i , Q j ) (P_i,Q_j) (Pi,Qj) 有边时的距离没有解决。由于整张图中没有入度大于 X X X 的点,故 Q Q Q 中每个点会往 P P P 中连至少一条边。而因为 Q Q Q 往 P P P 连的点是 P P P 的一个前缀,因此一定会连到 P 1 P_1 P1,故 d i s ( Q j , P i ) = 2 dis(Q_j,P_i)=2 dis(Qj,Pi)=2.
最后总结一下结论:
d
i
s
(
P
i
,
P
j
)
=
1
⇔
i
<
j
dis(P_i,P_j)=1\Leftrightarrow i\lt j
dis(Pi,Pj)=1⇔i<j
d
i
s
(
P
i
,
P
j
)
=
2
⇔
j
<
i
∧
∣
i
n
Q
(
P
i
)
∣
≠
∣
i
n
Q
(
P
j
)
∣
dis(P_i,P_j)=2\Leftrightarrow j\lt i\land |inQ(P_i)|\ne |inQ(P_j)|
dis(Pi,Pj)=2⇔j<i∧∣inQ(Pi)∣=∣inQ(Pj)∣
d
i
s
(
P
i
,
P
j
)
=
3
⇔
j
<
i
∧
∣
i
n
Q
(
P
i
)
∣
=
∣
i
n
Q
(
P
j
)
∣
dis(P_i,P_j)=3\Leftrightarrow j\lt i\land |inQ(P_i)|=|inQ(P_j)|
dis(Pi,Pj)=3⇔j<i∧∣inQ(Pi)∣=∣inQ(Pj)∣
d
i
s
(
Q
i
,
Q
j
)
=
1
⇔
i
<
j
dis(Q_i,Q_j)=1\Leftrightarrow i\lt j
dis(Qi,Qj)=1⇔i<j
d
i
s
(
Q
i
,
Q
j
)
=
2
⇔
j
<
i
∧
∣
i
n
P
(
Q
i
)
∣
≠
∣
i
n
P
(
Q
j
)
∣
dis(Q_i,Q_j)=2\Leftrightarrow j\lt i\land |inP(Q_i)|\ne |inP(Q_j)|
dis(Qi,Qj)=2⇔j<i∧∣inP(Qi)∣=∣inP(Qj)∣
d
i
s
(
Q
i
,
Q
j
)
=
3
⇔
j
<
i
∧
∣
i
n
P
(
Q
i
)
∣
=
∣
i
n
P
(
Q
j
)
∣
dis(Q_i,Q_j)=3\Leftrightarrow j\lt i\land |inP(Q_i)|=|inP(Q_j)|
dis(Qi,Qj)=3⇔j<i∧∣inP(Qi)∣=∣inP(Qj)∣
d
i
s
(
P
i
,
Q
j
)
+
d
i
s
(
Q
j
,
P
i
)
=
3
dis(P_i,Q_j)+dis(Q_j,P_i)=3
dis(Pi,Qj)+dis(Qj,Pi)=3
时间复杂度 O ( n 2 ) O(n^2) O(n2).
代码
#include<bits/stdc++.h>
#define llong long long
#define mkpr make_pair
#define x first
#define y second
#define iter iterator
#define riter reversed_iterator
#define y1 Lorem_ipsum_dolor
using namespace std;
inline int read()
{
int x = 0,f = 1; char ch = getchar();
for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}
for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}
return x*f;
}
const int mxN = 8000;
int ind[mxN+3];
vector<int> s1,s2;
char a[mxN+3][mxN+3];
queue<int> que;
int n; llong w,ans;
char decode(char x) {return x>=65?x-55:x-48;}
bool cmp(int x,int y) {return a[x][y];}
int main()
{
scanf("%d",&n); w = 614ll*n;
for(int i=1; i<=n; i++)
{
char ch = getchar();
for(int j=4; j<=n; j+=4)
{
ch = decode(getchar());
a[i][j-3] = (ch&8)>>3,a[i][j-2] = (ch&4)>>2,a[i][j-1] = (ch&2)>>1,a[i][j] = ch&1;
}
}
for(int i=1; i<=n; i++) for(int j=i+1; j<=n; j++)
{
if(a[i][j]) {ind[j]++;} else {ind[i]++;}
}
for(int i=1; i<=n; i++) if(ind[i]==0) {que.push(i);}
int cur = n;
while(!que.empty())
{
int u = que.front(); que.pop();
cur--; ans += (w+1ll)*cur;
for(int v=1; v<=n; v++) if(a[u][v]&&v!=u)
{
ind[v]--;
if(ind[v]==0) {que.push(v);}
}
}
if(cur==0) {printf("%I64d\n",ans); return 0;}
int u = 0; for(int i=1; i<=n; i++) if(u==0||ind[i]>ind[u]) {u = i;}
for(int i=1; i<=n; i++) if(ind[i]) {if(u==i||a[i][u]) {s1.push_back(i);} else {s2.push_back(i);}}
sort(s1.begin(),s1.end(),cmp); sort(s2.begin(),s2.end(),cmp);
ans += 3ll*s1.size()*s2.size()+s1.size()*(s1.size()-1ll)/2ll+s2.size()*(s2.size()-1ll)/2ll;
for(int i=0; i<s1.size(); i++) {ind[s1[i]] -= i;}
for(int i=0; i<s1.size(); i++) for(int j=0; j<i; j++)
{
ans += ind[s1[i]]==ind[s1[j]]?3ll:2ll;
}
for(int i=0; i<s2.size(); i++) {ind[s2[i]] -= i;}
for(int i=0; i<s2.size(); i++) for(int j=0; j<i; j++)
{
ans += ind[s2[i]]==ind[s2[j]]?3ll:2ll;
}
printf("%I64d\n",ans);
return 0;
}