CF117C Cycle 解题报告
1 题目链接
2 题目大意
题目 : 循环
题目大意 :
给定一个竞赛图,试给出一个大小为
3
3
3的环,若没有,输出-1
。
竞赛图的定义:一个没有自环的有向图,其中每一对顶点都由一个有向边连接。
3 解法分析
首先不用思考,直接
d
f
s
dfs
dfs(上头)。
没想到
d
f
s
dfs
dfs咋办(如本蒟蒻)?我们知道竞赛图有一条性质 : 若该竞赛图有环,则至少存在一个大小为
3
3
3的环(证明见后文)。
那么,这又是一种极简的方法。(也许?)
4 解法总结
4.1 暴力 d f s dfs dfs
甭多说,搜三层就完了。
4.2 数学方法
本蒟蒻认为这个方法十分简单 (逃),所以可以直接看代码。
5 性质证明
本蒟蒻采取数学归纳法证明。
当
n
=
3
n=3
n=3时显然成立。
设当
n
∈
[
3
,
k
]
n\in[3,k]
n∈[3,k]时结论成立,即证
n
=
k
+
1
n=k+1
n=k+1时结论亦成立。
十分显然,可以不断删去一个点或多个点使得剩下的图仍为竞赛图且点的个数
p
∈
[
3
,
k
]
p\in[3,k]
p∈[3,k]。
得证。
6 AC Code
Dalao代码 #001
// From KrK
// Rating 2810
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int Maxn = 5005;
int n;
char neigh[Maxn][Maxn];
int taken[Maxn], p[Maxn];
vector <int> res;
void tryGet(int v, int par)
{
taken[v] = 1; p[v] = par;
for (int i = 0; res.empty() && i < n; i++)
if (neigh[v][i] == '1')
if (taken[i] == 1) {
res.push_back(i);
while (v != i) {
res.push_back(v);
v = p[v];
}
} else if (!taken[i]) tryGet(i, v);
taken[v] = 2;
}
int main()
{
std::ios_base::sync_with_stdio(0);
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%s", neigh[i]);
for (int i = 0; i < n && res.empty(); i++)
if (!taken[i]) tryGet(i, -1);
if (res.empty()) cout << "-1\n";
else {
while (neigh[res[0]][res[res.size() - 2]] == '1') res.pop_back();
cout << res.back() + 1 << " " << res[res.size() - 2] + 1 << " " << res[0] + 1 << endl;
}
return 0;
}//KrK大佬的代码~!~
Dalao代码 #002
// From scott_wu
// Rating 3350
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
const int MAXN = 5100;
int n;
bool edge[MAXN][MAXN];
int num[MAXN];
//bool seen2[MAXN];
bool seen[MAXN];
int last[MAXN];
bool done;
int start;
vector <int> cyc, lcyc;
bool bad[MAXN];
char ch[MAXN];
/*void flood (int cur)
{
seen2[cur] = true;
for (int i = 0; i < beat[cur].size(); i++)
{
if (done) return;
if (seen[beat[cur][i]])
{
last[beat[cur][i]] = cur;
done = true;
lres = beat[cur][i];
}
else if (!seen2[beat[cur][i]])
{
last[beat[cur][i]] = cur;
seen[beat[cur][i]] = true;
flood (beat[cur][i]);
seen[beat[cur][i]] = false;
}
}
}*/
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
{
scanf ("%s",ch);
for (int j = 0; j < n; j++)
{
edge[i][j] = (ch[j] == '1');
if (edge[i][j])
num[i]++;
}
}
for (int i = 0; i < n; i++)
{
seen[i] = false;
bad[i] = false;
}
for (int i = 0; i < n; i++)
{
bool found = true;
for (int j = 0; j < n; j++)
{
if (num[j] == 0 && !bad[j])
{
found = false;
bad[j] = true;
for (int k = 0; k < n; k++)
if (edge[k][j])
num[k]--;
}
}
if (found) break;
}
int start = -1;
for (int i = 0; i < n; i++)
if (num[i] > 0)
start = i;
/*for (int i = 0; i < n; i++)
seen[i] = seen2[i] = false;
done = false;*/
//cout << start << "\n";
int cloc = start;
if (start == -1)
{
cout << "-1\n";
//system ("Pause");
return 0;
}
else
{
while (true)
{
if (seen[cloc]) break;
seen[cloc] = true;
for (int i = 0; i < n; i++)
if (edge[cloc][i] && !bad[i])
{
last[i] = cloc;
cloc = i;
break;
}
}
}
int cur = cloc;
do
{
cyc.push_back (cur);
cur = last[cur];
} while (cur != cloc);
while (cyc.size() > 3)
{
if (edge[cyc[0]][cyc[2]])
{
cout << cyc[0]+1 << " " << cyc[2]+1 << " " << cyc[1]+1 << "\n";
//system ("Pause");
return 0;
}
lcyc.clear();
for (int i = 0; i < cyc.size(); i++)
lcyc.push_back (cyc[i]);
cyc.clear();
for (int i = 0; i < lcyc.size(); i++)
if (i != 1)
cyc.push_back (lcyc[i]);
}
cout << cyc[0]+1 << " " << cyc[2]+1 << " " << cyc[1]+1 << "\n";
//system ("Pause");
return 0;
}
蒟蒻代码 #001
#include <bits/stdc++.h>
#define N 5007
using namespace std;
int n;
bool vis[N];
int G[N][N];
int tot[N];
int fa[N];
int top = 2;
void dfs(int u) {
if (vis[u]) return;
vis[u] = 1;
for (register int i = 0; i < tot[u]; ++i) {
register int v = G[u][i];
if (vis[v]) {
if (fa[fa[u]] == v) {
printf("%d %d %d", fa[fa[u]], fa[u], u);
exit(0);
}
continue;
}
fa[v] = u;
dfs(v);
}
}
inline void bfs(int s) {
queue <int> q;
q.push(s);
vis[s] = 1;
while (!q.empty()) {
register int u = q.front();
for (register int i = 0; i < tot[u]; ++i) {
register int v = G[u][i];
if (vis[v]) {
if (fa[fa[u]] == v) {
printf("%d %d %d", fa[fa[u]], fa[u], u);
exit(0);
}
continue;
}
fa[v] = u;
vis[v] = 1;
q.push(v);
}
q.pop();
}
}
int main() {
scanf("%d", &n);
for (register int i = 1; i <= n; ++i)
for (register int j = 1; j <= n; ++j) {
char c = getchar();
while (c != '0' && c != '1')
c = getchar();
if (c & 1) {
G[i][tot[i]++] = j;
}
}
for (register int i = 1; i <= n; ++i)
dfs(i);
for (register int i = 1; i <= n; ++i)
vis[i] = 0;
for (register int i = 1; i <= n; ++i)
bfs(i);
puts("-1");
return 0;
}//本蒟蒻也不理解为什么dfs和bfs各跑一遍就过了
蒟蒻代码 #002
#include <bits/stdc++.h>
#define rep(i, a, b) for (register int (i) = (a); (i) <= (b); ++(i))
using namespace std;
int n, vis[5007];
char a[5007][5007];
int main() {
scanf("%d", &n);
rep(i, 1, n)
scanf("%s", a[i] + 1);
rep(i, 1, n)
rep(j, 1, n)
if (a[i][j] == 49 && (!vis[i] || a[j][vis[i]] == 49))
vis[i] = j;
rep(i, 1, n)
rep(j, 1, n)
if (a[vis[i]][j] == 49 && a[j][i] == 49)
return printf("%d %d %d\n", i, vis[i], j), 0;
puts("-1");
return 0;
}//数学方法
7 胡言乱语
奇妙的水题又增加了~
找大佬代码的时候猛然发现
d
j
q
_
c
p
p
djq\_cpp
djq_cpp大佬现在是第六啊!