MnZn 拓扑求调
查看原帖
MnZn 拓扑求调
787990
Orz_Fa楼主2023/3/24 22:16

rt,这题从缩点题解过来的,一看拓扑能做就写了。 写完了之后调半天92pts,啥错都看不出来了。。。

然后看题解换成了题解的非拓扑做法ac了

(推测是拓扑写挂了)

#include <iostream>
#include <cstdio>
#include <queue>
#include <stack>
#include <map>
#define maxn 10010
#define maxm 50010
#define ll long long
using namespace std;
ll n,m;
struct fw
{
	ll next,to;
}a[maxm],f[maxm];
ll head[maxn],dfn[maxn],low[maxn],vis[maxn],cnt,scc,dis[maxn],id[maxn],x[maxm],y[maxm],rd[maxn];
stack <ll> p;
queue <ll> q;
map <ll,map<ll,ll> > mp;
void dfs(ll k)
{
	dfn[k]=low[k]=++cnt;
	vis[k]=1;
	p.push(k);
	for(int i=head[k];i;i=a[i].next)
	{
		ll v=a[i].to;
		if(!dfn[v]) dfs(v);
		if(vis[v]) low[k]=min(low[k],low[v]);
	}
	if(low[k]==dfn[k])
	{
		++scc;
		ll sum=0;
		while(1)
		{
			ll u=p.top();
			p.pop();
			vis[u]=0;
			id[u]=scc;
			sum++;
			if(u==k) break;
		}
		dis[scc]=sum;
	}
}
void topu()
{
	for(int i=1;i<=scc;i++) if(rd[i]==0) q.push(i);
	while(!q.empty())
	{
		ll u=q.front();
		q.pop();
		for(int i=head[u];i;i=f[i].next)
		{
			ll v=f[i].to;
			dis[v]+=dis[u];
			rd[v]--;
			if(rd[v]==0) q.push(v);
		}
	}
	ll ans=0;
	for(int i=1;i<=n;i++) if(dis[id[i]]==n) ans++;
	cout<<ans<<"\n";
	return;
}
int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>x[i]>>y[i];
		a[++cnt].next=head[x[i]];
		a[cnt].to=y[i];
		head[x[i]]=cnt;
	}
	cnt=0;
	for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i);
	cnt=0;
	for(int i=1;i<=n;i++) head[i]=0;
	for(int i=1;i<=m;i++)
	{
		ll u=id[x[i]],v=id[y[i]];
		if(u!=v&&!mp[u][v])
		{
			mp[u][v]=1;
			rd[v]++;
			f[++cnt].next=head[u];
			f[cnt].to=v;
			head[u]=cnt;
		}
	} 
	topu();
	return 0;
}
2023/3/24 22:16
加载中...