我要講的其實是下面這道題:
對於n個數,一直它們間m對關係(即pi>pj),問至少還需要知道多少堆關係才能將它們排序。
問題理解起來很簡單,相信有的讀者一眼看去就知道是拓撲排序(我一開始也是這麼認為的),那麼我就僅僅附上拓撲排序的**,因為我真正要講的,並不是拓撲排序法
#includeusingnamespace
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中我們能夠計算出已知關係的數量,從而最終確定答案。下面我附上**,注意當你看不懂輸出的時候,**下面我還會給予講解(當然自己想想也不錯),上面拓撲排序的**輸出也是一樣的。
#includeusingnamespace
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...