题解 有向图
首先发现那个 的条件很奇怪
貌似可以随机化找到一个有趣的点,再利用这个点去找别的点
发现从这个点开始dfs得到的dfs树上仅有树边和返祖边
于是一个点无趣的条件是同时在超过一个环中或其子树内存在一条连向一个无趣点的返祖边
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define pb push_back
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, m;
int head[N], size;
struct edge{int to, next, rk;}e[N<<1];
inline void add(int s, int t) {e[++size]={t, head[s]}; head[s]=size;}
namespace force{
bool vis[N], anc[N];
int ans[N], top;
bool dfs(int u) {
anc[u]=vis[u]=1;
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (anc[v]) continue;
if (vis[v]) return 0;
if (!dfs(v)) return 0;
}
anc[u]=0;
return 1;
}
void solve() {
top=0;
for (int i=1; i<=n; ++i) {
// cout<<"i: "<<i<<endl;
for (int j=1; j<=n; ++j) vis[j]=anc[j]=0;
if (dfs(i)) ans[++top]=i;
}
for (int i=1; i<=top; ++i) printf("%d%c", ans[i], " \n"[i==top]);
}
}
namespace task1{
vector<int> to[N];
int in[N], bit[N], bit2[N], res[N], siz[N], sum[N], rot, tot, qsiz;
bool vis[N], anc[N], disable[N], ans[N];
struct que{int l, r, rk;};
vector<que> q[N];
inline void upd(int i, int dat) {for (; i<=n; i+=i&-i) bit[i]+=dat;}
inline int query(int i) {int ans=0; for (; i; i-=i&-i) ans+=bit[i]; return ans;}
inline void upd2(int i, int dat) {for (; i<=n; i+=i&-i) bit2[i]+=dat;}
inline int query2(int i) {int ans=0; for (; i; i-=i&-i) ans+=bit2[i]; return ans;}
bool dfs1(int u) {
anc[u]=vis[u]=1;
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (anc[v]) continue;
if (vis[v]) return 0;
if (!dfs1(v)) return 0;
}
anc[u]=0;
return 1;
}
int getrt() {
for (int i=1; i<=n; ++i) disable[i]=0;
while (1) {
int t;
do {t=rand()%n+1;} while (disable[t]);
for (int i=1; i<=n; ++i) vis[i]=anc[i]=0;
if (dfs1(t)) return t;
else disable[t]=1;
}
}
void dfs2(int u) {
// cout<<"dfs2: "<<u<<endl;
in[u]=++tot;
siz[u]=1; anc[u]=1;
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (!anc[v]) dfs2(v), siz[u]+=siz[v];
}
anc[u]=0;
}
void dfs3(int u) {
anc[u]=1;
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (!anc[v]) dfs3(v);
else to[v].pb(u), q[v].pb({in[u], in[u]+siz[u]-1, e[i].rk=++qsiz});
}
anc[u]=0;
}
void dfs4(int u) {
anc[u]=1;
sum[u]=query(in[u]+siz[u]-1)-query(in[u]-1);
if (sum[u]>1) ans[u]=1;
if (query2(in[u]+siz[u]-1)-query2(in[u]-1)) ans[u]=1;
for (auto it:q[u]) res[it.rk]=query(it.r)-query(it.l);
for (auto it:to[u]) upd(in[it], 1); //, cout<<"at: "<<u<<' '<<it<<' '<<1<<endl;
if (ans[u]) for (auto it:to[u]) upd2(in[it], 1);
for (int i=head[u],v; ~i; i=e[i].next) {
v = e[i].to;
if (!anc[v]) dfs4(v);
else if (sum[v]>1) {
// cout<<"dfs4: "<<u<<' '<<v<<' '<<e[i].rk<<endl;
// if (sum[v]-res[e[i].rk] > 1) ans[u]=1;
ans[u]=1;
}
}
if (ans[u]) for (auto it:to[u]) upd2(in[it], -1);
for (auto it:to[u]) upd(in[it], -1);
anc[u]=0;
}
void solve() {
rot=getrt(); tot=qsiz=0;
// cout<<"rot: "<<rot<<endl;
for (int i=1; i<=n; ++i) bit[i]=bit2[i]=sum[i]=0, to[i].clear(), q[i].clear();
for (int i=1; i<=n; ++i) anc[i]=ans[i]=0;
dfs1(rot); dfs2(rot); dfs3(rot); dfs4(rot);
for (int i=1; i<=n; ++i) if (!ans[i]) printf("%d ", i); printf("\n");
// cout<<"in: "; for (int i=1; i<=n; ++i) cout<<in[i]<<' '; cout<<endl;
// cout<<"siz: "; for (int i=1; i<=n; ++i) cout<<siz[i]<<' '; cout<<endl;
// for (int i=1; i<=n; ++i) {
// cout<<"i: "<<i<<':';
// for (auto it:to[i]) cout<<it<<' '; cout<<endl;
// }
// cout<<"qsiz: "<<qsiz<<endl;
// cout<<"res: "; for (int i=1; i<=qsiz; ++i) cout<<res[i]<<' '; cout<<endl;
// cout<<"sum: "; for (int i=1; i<=n; ++i) cout<<sum[i]<<' '; cout<<endl;
}
}
signed main()
{
freopen("graph.in", "r", stdin);
freopen("graph.out", "w", stdout);
int T=read();
for (int k=1; k<=T; ++k) {
n=read(); m=read(); size=0;
// if (k==1108) cout<<n<<' '<<m<<endl;
memset(head, -1, sizeof(int)*(n+5));
for (int i=1,u,v; i<=m; ++i) {
u=read(); v=read();
// if (k==1108) cout<<u<<' '<<v<<endl;
add(u, v);
}
// force::solve();
task1::solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)