CF915D Almost Acyclic Graph 拓扑排序
题面
题意:
给n个点,m条边,有向图,求是否能去掉一条边使得原图无环。
n<=500,m<=min(n(n−1),105)
题解
一个朴素的想法:
枚举删哪条边,然后用拓扑排序判断是否还有环。
但是复杂度直接爆炸。
我们考虑删边对我们check过程(拓扑排序)的影响。
删掉一条边,相当于使得它的出点入度减一。
那么不管我们删掉哪条边,只要它的出点一致,那么在拓扑排序看来,我们的操作其实效果一样。
也就是这样会造成大量无用且重复的判断。
所以我们考虑枚举点。
如果一个点有入度,那么我们尝试删除一条到这个点的边,也就是让这个点入度减一,然后用拓扑排序判断一下是否有环。
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 600
#define ac 101000
int n, m;
int in[AC], s[AC];
int q[AC], head, tail;
int Head[AC], date[ac], Next[ac], tot;
inline int read()
{
int x = 0;char c = getchar();
while(c > '9' || c < '0') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
}
inline void add(int f, int w){//加单项边
date[++ tot] = w, Next[tot] = Head[f], Head[f] = tot, in[w] ++, s[w] ++;
}
void pre()
{
n = read(), m = read();
for(R i = 1; i <= m; i ++)
{
int x = read(), y = read();
add(x, y);
}
}
bool t_sort()
{
head = 1, tail = 0;
for(R i = 1; i <= n; i ++)
if(!in[i]) q[++ tail] = i;
while(head <= tail)
{
int x = q[head ++];
for(R i = Head[x]; i; i = Next[i])
{
int now = date[i];
if(!(-- in[now])) q[++ tail] = now;
}
}
return tail == n;
}
void work()
{
for(R i = 1; i <= n; i ++)
{
if(!in[i]) continue;
-- in[i];
if(t_sort())
{
printf("YES\n");
return ;
}
memcpy(in, s, (n + 1) * 4);
// for(R j = 1; j <= n; j ++) in[j] = s[j];
}
printf("NO\n");
}
int main()
{
// freopen("in.in", "r", stdin);
pre();
work();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
2018-10-14 51nod1254 最大子段和 V2 DP