標籤:return 就是 cst 入門 題目 傳遞 out 集合 node
poj2186tarjan演算法縮點求出度
自己打一遍第一題,入門啦,入門啦
題目還算簡單,多頭牛,給你仰慕關係(可傳遞),問你最後有沒有牛被所有的牛仰慕
根據關係可以建圖,利用tarjan演算法縮點處理後,得到有向非循環圖,縮成的點都是相互仰慕的,所以根據傳遞性也就是可以看成一個點了,然後染色分塊,計算每一塊的出度。
如果出度為0有且僅有一個,那麼輸出該塊內所有的點,都符合要求
如果有多個直接輸出0即可
#include <iostream>#include <cstdio>#include <string.h>using namespace std;const int maxn = 10005;const int maxm = 100005;struct node{ int to,pre;}e[maxm];int n,m;int idx;int id[maxn],cnt;int dfn[maxn],low[maxn];int stack1[maxn],s_top;int out[maxn];int color[maxn];int vis[maxn];int cut_point = 0;void init(){ memset(dfn,0,sizeof(dfn)); memset(vis,0,sizeof(vis)); memset(color,0,sizeof(color)); memset(low,0,sizeof(low)); memset(id,-1,sizeof(id)); memset(out,0,sizeof(id)); cnt = 0; idx = 0; s_top = 0; cut_point = 0;}void add(int u,int v){ e[cnt].to = v; e[cnt].pre = id[u]; id[u] = cnt++;}void tarjan(int u, int pre){ dfn[u] = low[u] = ++idx; vis[u] = 1; stack1[s_top++] = u; for(int i = id[u];~i;i = e[i].pre) { int v = e[i].to; if(!vis[v]) { tarjan(v,u); low[u] = min(low[v],low[u]); } else { low[u] = min(low[u],dfn[v]); } } if(low[u] == dfn[u]) { cut_point++;//顏色1 。。。n while(s_top > 0 && stack1[s_top] != u)//目的是先處理完元素在判斷是不是最後一個 { s_top--; vis[stack1[s_top]] = 2; color[stack1[s_top]] = cut_point; } }}int main(){ int u,v; while(~scanf("%d%d",&n,&m)) { //初始化 init(); //添加邊 for(int i = 0;i < m;i++) { scanf("%d%d",&u,&v); add(u,v); } //縮點處理——染色 for(int i = 1;i <= n;i++)//防止不連通的情況 { if(!vis[i]) { tarjan(i,-1); } } //染色成功後,記錄出度 for(int i = 1;i <= n;i++) { for(int j = id[i];~j;j = e[j].pre) { int v = e[j].to; if(color[i] != color[v]) { ++out[color[i]]; } } } //看看度為0的點的集合,找出所有的點 //color還要一樣,不能有兩個 int sum = 0,p_color; for(int i = 1;i <= cut_point;i++) { if(!out[i]) sum++,p_color = i; } if(sum == 1) { int ans = 0; for(int i = 1;i <= n;i++) { if(color[i] == p_color)ans++; } printf("%d\n",ans); } else { puts("0"); } } return 0;}
poj2186tarjan演算法縮點求出度