靜態傳遞閉包

2022-04-30 02:00:07 字數 1684 閱讀 8563

我要講的其實是下面這道題:

對於n個數,一直它們間m對關係(即pi>pj),問至少還需要知道多少堆關係才能將它們排序。

問題理解起來很簡單,相信有的讀者一眼看去就知道是拓撲排序(我一開始也是這麼認為的),那麼我就僅僅附上拓撲排序的**,因為我真正要講的,並不是拓撲排序法

#includeusing

namespace

std;

const

int maxn=1000+15

;int

n,m,sum;

inthead[maxn],vis[maxn];

bitset

rel[maxn];

struct

edge

edge[maxn*20

];void add(int x,int

y)void dfs(intx)}

intmain()

for (int i=1;i<=n;i++)

if (!vis[i]) dfs(i);

int ans=0

;

for (int i=1;i<=n;i++) ans+=rel[i].count();

printf("%d

",n*(n-1)/2-ans+n);

return0;

}

之所以不講,是因為我認為我還不能完全的理解

下面我來介紹一種更為簡單的方法(floyd)

首先告訴大家這題的資料,n<=1000,那麼正常情況下n^3的floyd肯定是不行的了,有個操作叫做手動壓位能降低複雜度,然而我不會。我會的方法並不是手動的,而是利用stl庫里的bitset進行優化

應該有不少的人不知道bitset是何物,我推薦乙個我自己發現的一篇部落格,希望對大家有幫助bitset講解

利用已知關係,我們得到了一張有向無環圖,對於任兩點i j,若是i能夠到j,這對於乙個j能到的點集,i都能到達點集中的任意一點(聯通)。可以明確,如果給定的關係為0,排序之後我們知道的關係就是n(n-1)/2(對於任意互異兩點都知道關係),那麼在floyd中我們能夠計算出已知關係的數量,從而最終確定答案。下面我附上**,注意當你看不懂輸出的時候,**下面我還會給予講解(當然自己想想也不錯),上面拓撲排序的**輸出也是一樣的。

#includeusing

namespace

std;

const

int maxn=1000+15

;int

n,m;

bitset

rel[maxn];

intmain()

for (int i=1;i<=n;i++)

for (int j=1;j<=n;j++)

if (rel[j][i]) rel[j]|=rel[i];//

注意是判斷rel[j][i],而不是rel[i][j](迴圈好像不能反過來寫)

int ans=0

;

for (int i=1;i<=n;i++)

ans+=rel[i].count();

printf("%d

",n*(n-1)/2-ans+n);

return0;

}

輸出講解:注意一開始我們對所有的i,都有bitset[i][i]=true,因此我們最後要給已知的關係數ans減去n,之後再計算

flord 傳遞閉包

傳遞指對於乙個節點i,如果j能到i,i能到k,那麼j就能到k。傳遞閉包,就是把圖中所有滿足這樣傳遞性的節點都弄出來,計算完成後,我們也就知道任意兩個節點之間是否相連。break 指跳出一層迴圈 continue 結束本次迴圈,跳過本次判斷語句 每只奶牛的技能獨一無二,如果給奶牛們排序的話,能確定自己...

floyd傳遞閉包

傳遞閉包 我第一反應是凸包emmm 就是把具有傳遞性的關係傳遞開。一般我們用一鄰接矩陣儲存。比如許多的並查集解決的問題,如果需要細緻 效率o n 可以用傳遞閉包去做。看一道題吧,poj1094,不等式的傳遞性。這道題在處理方面,d i,j 為1時表示i1 矛盾與不確定,優先矛盾。2 若加入了幾個,發...

閉包傳遞(floyed)

題目大意 n代表母牛的個數,m代表給定的資訊的組數。每一組數包括a,b.代表b崇拜a 突然發現可以用tarjan演算法做 然後問你最終有多少母牛的地位是確定的。include include include include include include include include includ...