0%

[QOJ9246] Dominating Point

暴力能冲过去的神秘结论题。

补一发正解。

题目链接

题意

给定一张 个点的竞赛图。

称一个点 是支配点,当且仅当 可以在两步以内到达其余所有点。

求出这张图的至少三个支配点,或判断无解。

题解

结论 :整张图中出度最大的点是支配点。

设出度最大的点是 ,并设 为所有 连向的点, 为所有连向 的点。

那么 可以一步直接到达 内的所有点。

其次, 可以两步到达 内的所有点。可以使用反证法。

不能两步到达 ,则 连向 内所有点。

又因为 ,所以 连向 ,那么 的度数是

度数最大矛盾,所以 是整张图的支配点。

然后若 ,那么显然整张图只有这一个支配点。

否则,,我们可以求出 的支配点

因为 ,那么 可以一步走到 ,进而可以两步内走到

又因为 的支配点,所以 可以两步内走到 的所有点。

所以 也是整张图的支配点。

然后,若 的度数 ,我们可以使用同样的方案,再求出一个支配点

否则, 可以一步到达 内的所有点。

中连向 的点, 连向的点。

则我们求出 的支配点 可以一步到达 ,进而两步到达

所以 也是整张图的支配点。

这样我们就可以求出这张图的至少三个支配点。

时间复杂度

代码

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
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3fll
#define debug(x) cerr<<#x<<"="<<x<<endl
using namespace std;
using ll=long long;
using ld=long double;
using pli=pair<ll,int>;
using pi=pair<int,int>;
template<typename A>
using vc=vector<A>;
inline int read()
{
int s=0,w=1;char ch;
while((ch=getchar())>'9'||ch<'0') if(ch=='-') w=-1;
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
char s[5001][5002];
int S[5001];
int T[5001];
int d[5001];
int a,b,c;
int n;
inline int get(int *S)
{
assert(S[0]);
memset(d,0,sizeof(d));
for(int i=1;i<=S[0];i++) for(int j=i+1;j<=S[0];j++)
{
if(s[S[i]][S[j]]=='1') d[S[i]]++;
else d[S[j]]++;
}
int v=S[1];bool f=0;
for(int i=2;i<=S[0];i++) if(d[S[i]]>d[v]) v=S[i];
for(int i=1;i<=S[0];i++) if(s[S[i]][v]) f=1;
return v;
}
int main()
{
n=read();
for(int i=1;i<=n;i++) scanf("%s",s[i]+1),S[++S[0]]=i;
a=get(S),S[0]=0;
if(d[a]==n-1)
{
printf("NOT FOUND\n");
return 0;
}
for(int i=1;i<=n;i++) if(a!=i)
{
if(s[a][i]=='1') S[++S[0]]=i;
else T[++T[0]]=i;
}
b=get(T);
if(d[b]!=T[0]-1)
{
S[0]=0;
for(int i=1;i<=T[0];i++) if(T[i]!=b&&s[b][T[i]]=='0') S[++S[0]]=T[i];
c=get(S);
}
else
{
T[0]=0;
for(int i=1;i<=S[0];i++) if(s[S[i]][b]=='1') T[++T[0]]=S[i];
c=get(T);
}
printf("%d %d %d\n",a,b,c);
return 0;
}

感谢观看!