毒瘤演算法系列13 情報傳遞

2021-10-06 22:40:10 字數 2544 閱讀 1312

有乙個情報網共有n

nn個人,通過有向的**線聯絡。為保證通訊安全,需要滿足一些要求,這些要求分為兩類:

現在作為總工程師的你需要構造乙個合法的情報網,使得這個情報網滿足給定要求,或者告訴情報機構這樣的情報網是不存在的。

這道題a

aa如果到b

bb的情況一定滿足的話,一定要在滿足這對條件的情況下,其它對盡量難以到達,這是一種貪心的最優策略。因此我們只要將①

①①中的邊連線起來,在判斷②

②②是否合法即可。

那麼我們如何判斷合法呢?顯然我們只需要用tarjan縮點判斷a能否到達b即可。判斷方法就是用陣列暴力標記,類似於二維的dp:f[i

][j]

f[i][j]

f[i][j

]表示當前節點i

ii是否是節點j

jj所能到達的。

這樣轉移的複雜度是不優秀的:o(n

2)

o(n^2)

o(n2).

由於這只是0/1狀態,如果我們使用bitset中的或操作,複雜度可以優化到:o(n

264

)o(\frac)

o(64n2

​).此時空間複雜度不允許,我們每一次限制第二維在一定區間內進行多次操作,可以保證時間複雜度不改變,空間複雜度可以進行進一步優化。這種操作的方法類似於分塊來優化空間。

#include

using

namespace std;

const

int n =

1e5+10;

const

int k =

20000

;int n, m,

top(0)

,cnt(0

),scc(0)

, k;

int dfn[n]

, low[n]

, st[n]

, col[n]

, x[n]

, y[n]

, in[n]

, in[n]

, piga[n]

, pigb[n]

;int link1[n]

, tot1 =0;

int link2[n]

, tot2 =0;

struct node e1[n *2]

, e2[n *2]

;bitset < k +

10> f[n]

;int

read

(void

)void

tarjan

(int x)

else

if(in[y]

) low[x]

=min

(low[x]

,dfn[y]);

}if(low[x]

== dfn[x]

)return;}

bool

check

(int l,

int r)

for(

int i=

1;i<=scc;

++i)

while

(q.size()

)}for(

int i=

1;i<=k;

++i)

if(f[col[pigb[i]]]

[col[piga[i]]]

)return0;

return1;

}void

add1

(int x,

int y)

; link1[x]

= tot1;

}void

add2

(int x,

int y)

; link2[x]

= tot2;

}int

main

(void

)for

(int i=

1;i<=n;

++i)

if(dfn[i]==0

)tarjan

(i);

for(

int x=

1,y;x<=n;

++x)

for(

int i=link1[x]

;i;i=e1[i]

.next)

k =read()

;for

(int i=

1;i<=k;

++i)

piga[i]

=read()

, pigb[i]

=read()

;for

(int i=

1,j;i<=scc;i=j+1)

puts

("yes");

printf

("%d\n"

, m)

;for

(int i=

1;i<=m;

++i)

printf

("%d %d\n"

, x[i]

, y[i]);

return0;

}

毒瘤演算法系列3 負環 倍增Floyed

給定一張邊帶權的無向圖g gg,請你找出乙個點數最少的環,使得環上的邊權和為負數。保證圖中不存在重邊和自環。這道題其實最容易想到的時二分,我們去限制邊的長度,判斷是否存在小於等於這個邊權的負環。但是這麼考慮我們實現最後的判斷,我們可以使用倍增來限制邊權的長度。對於每一次的倍增,我們假設需要判定是否存...

毒瘤演算法系列12 最大流 邊雙連通分量 雜湊

給定一張n nn個點 m mm條邊的無向圖,點從1 11開始編號,保證所有點的度數都不超過333。現在假定每條邊的容量都為1 11,請你求出任意兩點間的最大流,最後只要輸出所有點對 i,j i,ji,j i i j 間最大流的和。對於這道題目,突破口便在於任意點的度數不超過333.最大流的定義 兩點...

java演算法系列

棧的概念 棧是一種特殊的線性表,堆疊的資料元素以及資料元素之間的關係和線性表是完全一樣的。差別是線性表是在任意位置進行插入和刪除操作,棧是只允許在固定的一端進行插入和刪除,棧的插入和刪除只允許在棧頂,棧的插入和刪除通常稱為進棧和出棧。資料集合 每個資料元素的資料型別可以是任意的型別 操作的集合 進棧...