题解 回路
其实乱搞能过
正解(粘的题解):
每次从队头取出一个点 \(u\) 后,遍历它连向的所有节点 \(v\) ,若 \(u\) 已经在队列中且不是 \(v\) 的前驱
那么说明我们已经找到了一条非平凡回路,并且这一定是最短的。此时 \(u\) 的最短路 \(+1\) 就是答案
每个点最多入队一遍,因此是 \(O(n^2)\) 的
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 5010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#define int long long
int n;
char s[N];
vector<int> e[N];
namespace task1{
queue<int> q;
int back[N], dis[N], ans;
void bfs(int s) {
q.push(s);
// int cnt=0;
while (q.size()) {
int u=q.front(); q.pop();
// ++cnt;
for (auto& v:e[u])
if (dis[v]>dis[u]+1) {
dis[v]=dis[u]+1;
back[v]=u; q.push(v);
}
else if (v!=back[u]) ans=min(ans, dis[u]+dis[v]+1);
}
// cout<<"cnt: "<<cnt<<endl;
}
void solve() {
for (int i=1; i<=n; ++i) {
// cout<<"i: "<<i<<endl;
memset(dis, 0x3f, sizeof(dis));
memset(back, -1, sizeof(back));
dis[i]=0; ans=INF;
bfs(i);
printf("%d\n", ans==INF?-1:(ans+1)/2);
}
}
}
namespace task2{
queue<int> q;
int back[N], dis[N], ans;
void bfs(int s) {
q.push(s);
// int cnt=0;
while (q.size()) {
int u=q.front(); q.pop();
// ++cnt;
if (2*dis[u]>=ans) continue;
if (ans==3) continue;
for (auto& v:e[u])
if (dis[v]>dis[u]+1) {
dis[v]=dis[u]+1;
back[v]=u; q.push(v);
}
else if (v!=back[u]) ans=min(ans, dis[u]+dis[v]+1);
}
// cout<<"cnt: "<<cnt<<endl;
}
void solve() {
for (int i=1; i<=n; ++i) {
// cout<<"i: "<<i<<endl;
memset(dis, 0x3f, sizeof(dis));
memset(back, -1, sizeof(back));
dis[i]=0; ans=INF;
bfs(i);
printf("%d\n", ans==INF?-1:(ans+1)/2);
}
}
}
signed main()
{
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
scanf("%d", &n);
for (int i=2; i<=n; ++i) {
scanf("%s", s+1);
for (int j=1; j<i; ++j) if (s[j]=='1')
e[i].pb(j), e[j].pb(i);
}
if (n<=200) task1::solve();
else task2::solve();
return 0;
}