题目大意
给定一些竹签它们有的压着别的竹签,有的被别的竹签压,在保证竹签塔不会坍塌的情况下,求出最多可以去除的竹签数
解题思路
思路1:
因为
->
,那么
就取出后就可以取出
,这样就满足拓扑序,若
,
之间互相约束彼此,那么它们就不会在拓扑序中,也就是不被选择,所以我们只需要跑一遍
计算入队次数就可以了
思路2
->
,这是单向传递,当且仅当两根竹签互相约束时不能求出,即为一个强连通分量,所以我们也可以用
缩点求解
但是由于本人太弱不会打Tarjan就不放代码啦哈哈哈
代码
#include<queue>
#include<cstdio>
#include<cstring>
#define M 1000001
using namespace std;int ans,tot,l[M],d[M],m,x,y,n;
queue<int>q;
struct node{int next,to;}e[M];
void add(int u,int v){e[tot]=(node){l[u],v};l[u]=tot++;return;}
int main()
{
freopen("mikado.in","r",stdin);
freopen("mikado.out","w",stdout);
memset(l,-1,sizeof(l));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d%d",&x,&y),add(x,y),d[y]++;
for(int i=1;i<=n;i++) if(!d[i]) q.push(i),ans++;//求出入度
while(q.size())
{
x=q.front();q.pop();
for(int i=l[x];~i;i=e[i].next) if(!(--d[e[i].to])) q.push(e[i].to),ans++;//计算入队次数
}
printf("%d",ans);//输出
}