強連通分量 搶掠計畫

2021-06-05 10:05:17 字數 2540 閱讀 8813

siruseri城中的道路都是單向的。不同的道路由路口連線。按照法律的規定,在每個路口都設立了乙個siruseri銀行的atm取款機。令人奇怪的是,siruseri的酒吧也都設在路口,雖然並不是每個路口都設有酒吧。 banditji計畫實施siruseri有史以來最驚天動地的atm搶劫。他將從市中心出發,沿著單向道路行駛,搶劫所有他途徑的atm機,最終他將在乙個酒吧慶祝他的勝利。 使用高超的黑客技術,他獲知了每個atm機中可以掠取的現金數額。他希望你幫助他計算從市中心出發最後到達某個酒吧時最多能搶劫的現金總數。他可以經過同一路口或道路任意多次。但只要他搶劫過某個atm機後,該atm機裡面就不會再有錢了。 例如,假設該城中有6個路口,道路的連線情況如下圖所示:

市中心在路口1,由乙個入口符號→來標識,那些有酒吧的路口用雙圈來表示。每個atm機中可取的錢數標在了路口的上方。在這個例子中,banditji能搶劫的現金總數為47,實施的搶劫路線是:1-2-4-1-2-3-5。

輸入格式

第一行包含兩個整數n、m。n表示路口的個數,m表示道路條數。接下來m行,每行兩個整數,這兩個整數都在1到n之間,第i+1行的兩個整數表示第i條道路的起點和終點的路口編號。接下來n行,每行乙個整數,按順序表示每個路口處的atm機中的錢數。接下來一行包含兩個整數s、p,s表示市中心的編號,也就是出發的路口。p表示酒吧數目。接下來的一行中有p個整數,表示p個有酒吧的路口的編號。

輸出格式

輸出乙個整數,表示banditji從市中心開始到某個酒吧結束所能搶劫的最多的現金總數。

資料範圍

50%的輸入保證n, m<=3000。所有的輸入保證n, m<=500000。每個atm機中可取的錢數為乙個非負整數且不超過4000。輸入資料保證你可以從市中心沿著siruseri的單向的道路到達其中的至少乙個酒吧。

輸入樣例

6 71 2

2 33 5

2 44 1

2 66 5

1012816

151 44 3 5 6

輸出樣例

47

這是一道強連通分量問題。

首先對原圖求所有強連通分量並進行縮點,建立新圖。

再用spfa演算法求最長路即可。(注意此時不能使用dijkstra演算法。)

accode:

#include #include #include #include #include #include #define max(a, b) ((a) > (b) ? (a) : (b))

#define min(a, b) ((a) < (b) ? (a) : (b))

using std::set;

using std::pair;

using std::make_pair;

const char fi = "atm.in";

const char fo = "atm.out";

const int maxn = 500010;

const int size = 0xfffff;

const int max = 0x3f3f3f3f;

const int min = ~max;

struct edge ;

edge *edge1[maxn], *edge2[maxn];

bool marked[maxn], bar[maxn], final[maxn];

int q[maxn], money[maxn], dist[maxn];

int cnt[maxn], dfn[maxn], low[maxn];

int belong[maxn], stack[maxn];

int n, m, s, p, top, index, bcnt, ans, f, r;

void init_file()

inline int getint()

inline void insert2(int u, int v)

inline void insert1(int u, int v)

void readdata()

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

money[i] = getint();

s = getint();

for (p = getint(); p; --p)

bar[getint()] = 1;

return;

}void tarjan(int u)

else if (marked[v])

low[u] = min(low[u], dfn[v]);

}if (low[u] == dfn[u])

while (tmp != u);

}return;

}inline int spfa()}}

return ans;

}void work()

int main()

#undef min

#undef max

強連通分量 tarjan求強連通分量

雙dfs方法就是正dfs掃一遍,然後將邊反向dfs掃一遍。挑戰程式設計 上有說明。雙dfs 1 include 2 include 3 include 4 include 5 6using namespace std 7const int maxn 1e4 5 8 vector g maxn 圖的鄰...

強連通分量

對於有向圖的乙個頂點集,如果從這個頂點集的任何一點出發都可以到達該頂點集的其餘各個頂點,那麼該頂點集稱為該有向圖的乙個強連通分量。有向連通圖的全部頂點組成乙個強連通分量。我們可以利用tarjan演算法求強連通分量。define n 1000 struct edge e 100000 int ec,p...

強連通分量

在有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強連通 strongly connected 如果有向圖g的每兩個頂點都強連通,稱g是乙個強連通圖。非強連通圖有向圖的極大強連通子圖,稱為強連通分量 strongly connected components 下圖中,子圖為乙個強連通分量,因為...