zoukankan      html  css  js  c++  java
  • P2002 消息扩散

    其实这道题蛮水的

    思路:

    根据题意,他说有环,自然想到要用tarjan,后面就很简单了;

    缩完点之后重新建图,开一个inin数组表示该点的入度是多少(psps:该点表示缩完点之后的大点);

    最后统计一下那个点没有入度就好了;

    下面是本蒟蒻的cpp
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<stack>
    using namespace std;
    #define maxn 10101110 stack
    <int>q; struct Node { int next,to; }e[maxn],ee[maxn]; int dfn[maxn],low[maxn],be[maxn]; int vis[maxn],in[maxn],headd[maxn]; int n,m,num,num1,ans,head[maxn]; //num1表示大点的个数,num表示tarjan中的编号 //head原图,e->原图;ee->新图 headd->新图 void add(int x,int y) { e[++head[0]].next=head[x]; e[head[0]].to=y; head[x]=head[0]; } void ad(int x,int y) { ee[++headd[0]].next=headd[x]; ee[headd[0]].to=y; headd[x]=headd[0]; } //这里我用的head[0],headd[0]表示是为了节省一个小小的空间 void tarjan(int x) { vis[x]=1;q.push(x); dfn[x]=low[x]=++num; for(int i=head[x];i;i=e[i].next) { int t=e[i].to; if(!dfn[t]) { tarjan(t); low[x]=min(low[x],low[t]); } else if(vis[t]) low[x]=min(low[t],low[x]); } if(dfn[x]==low[x]) { vis[x]=0; be[x]=++num1; while(q.top()!=x) { be[q.top()]=num1; vis[q.top()]=0; q.pop(); } be[q.top()]=num1; vis[q.top()]=0; q.pop(); } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int y,u; scanf("%d%d",&y,&u); add(y,u); }//加边 for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++) for(int j=head[i];j;j=e[j].next) if(be[i]!=be[e[j].to]) { ad(be[i],be[e[j].to]); in[be[e[j].to]]++; //加新边同时记in } for(int i=1;i<=num1;i++) if(!in[i]) ans++; printf("%d",ans); return 0; }
  • 相关阅读:
    Lucky Permutation Triple 构造
    HDU4283:You Are the One(区间DP)
    D. Match & Catch 后缀数组
    数学选讲 orz
    D
    一步一步线段树
    湖科大校赛第三题
    最大流部分
    bfs题目集锦
    hdu1429 bfs+状态压缩
  • 原文地址:https://www.cnblogs.com/lck-lck/p/9571852.html
Copyright © 2011-2022 走看看