小K的技术
小K的技术
考虑每个弱连通分量(即无视边的方向形成的各个连通分量,内部点彼此可达),答案是独立的。
而且对于一个弱连通分量,若不存在环,我们可以发现其实只需要点数 DAG
,所以可以让这个类似于一棵树。
而如果存在环,说明依赖关系并不是顺序结构,那么需要多一条边,而且根据一个环一定满足,那么最多也就
于是,我们对于每个弱连通分量判断是否存在环,如果不存在,答案就减去一。
关于环的判断,可以考虑黑白灰染色。对于每个点,未遍历时标记为
#include<cstdio>
#include<cstring>
#define sh short
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while
const int N=100010,M=2*N;
int n,m,ans,nidx;
int h[N],e[M],ne[M],idx,st[N];//don't forget memset h!
bool cir[N];
sh vis[N];
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void dfs(int x){
st[x]=nidx;
Ed{
int j=e[i];
if(!st[j])dfs(j);
}
}
bool Dfs(int x){
vis[x]=1;
Ed{
if(i&1)continue;
int j=e[i];
if(!vis[j]&&Dfs(j))return 1;
else if(vis[j]==1)return 1;
}
vis[x]=2;
return 0;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
memset(h,-1,n*4+4);
E(i, m){
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
int tot=n;
E(i, n)
if(!st[i])++nidx,dfs(i);
E(i, n){
if(cir[st[i]])continue;
if(!vis[i])cir[st[i]]=Dfs(i);
}
E(i, nidx)tot-=!cir[i];
printf("%d",tot);
return 0;
}
本文作者:wscqwq
本文链接:https://www.cnblogs.com/wscqwq/p/17668664.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步