P2863 [USACO06JAN]The Cow Prom S
阿新 • • 發佈:2020-08-11
這題是裸的tarjan,我來寫個部落格鞏固下知識。。。。
先求出每個強連通,然後判斷一下棧中的個數是否大於1就好了。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <stack> #include <queue> #include <map> #include <set> #include <list> using namespace std; #define GC getchar() #define R read() #define ll long long #define ull unsigned ll #define INF 0x7fffffff ll read(){ ll s=0,f=1; char c=GC; while(c<'0'||c>'9'){if(c=='-')f=-f;c=GC;} while(c>='0'&&c<='9'){s=s*10+c-'0';c=GC;} return s*f; } int n,m,a,b; vector<int> e[10010]; int dfn[10010],low[10010],vis[10010],cnt; stack<int> s; int num[10010],number,ans; void tarjan(int u){ dfn[u]=low[u]=++cnt;//初始化 vis[u]=1;s.push(u);//進棧 for(int i=0;i<e[u].size();++i){ int v=e[u][i]; if(!dfn[v]){//沒有去過 tarjan(v);//搜一下 low[u]=min(low[v],low[u]);//更新 }else if(vis[v]){//還在棧裡 low[u]=min(low[u],dfn[v]);//更新 } } if(low[u]==dfn[u]){//有強連通 ++number;//強連通個數++ int p=0; do{ p=s.top();s.pop();vis[p]=0;//記錄,出棧 ++num[number];//棧中個數++ }while(p!=u); if(num[number]>1){//判斷個數是否>1 ++ans; } } } int main(){ n=R;m=R; for(int i=1;i<=m;++i){ a=R;b=R; e[a].push_back(b); } for(int i=1;i<=n;++i){//搜 if(!dfn[i]){ tarjan(i); } } printf("%d",ans); return 0; }
啊好像也沒怎麼鞏固= =