給定n個點 其中p個點可以被賄賂, 被賄賂的金額為x,如果乙個點被賄賂,他所指向的點也會被賄賂
求:如果不能全部被賄賂 輸出no以及不能被賄賂的點 否則輸出yes和需要支付的金額的最小值
我們可以通過tarjan縮點,最後掃一遍dfn,若果有乙個點並沒有被訪問過,說明這個點肯定不會被賄賂 直接輸出並結束程式
那麼如果全部可以賄賂呢?我們想,乙個強聯通分量裡面隨便賄賂乙個點,其他的全部都會被賄賂 那麼我們是不是只在需要在進行tarjan的時候進行比較,求出最小值即可
然而 如果乙個強聯通分量指向另乙個強聯通分量,我們就可以用指向另乙個的強聯通分量裡的最小值就可以了
有同學問:如果被指向的強聯通分量裡面有乙個比指向的最小值還小的值,是不是可以用呢?
答案是不可以的 如果選擇了指向的強聯通分量,我們的花費是x,此時因為他指向另乙個強聯通分量,所以另乙個不需要花錢,所以我們只需要統計入度為0的強聯通分量,並且累加答案就可以了
注意:在進行tarjan的時候while(stack[top]! = u)前面後面都要有乙個更新答案 因為有2中種特殊情況:u在棧頂和棧尾,當然你也可以不這麼寫,直接將top+1即可while(stack[top + 1] != u)
#include constac codeint inf = 1e9 + 10
;using
namespace
std;
intn, p, r, num, top, col, sh;
int mon[3010], coin[3010], head[10010], dfn[3010
];int st[3010], co[3010], low[3010], si[3010], vis[3010
];int ans[3010], ru[3010
];struct
emmm e[
10010
];void tarjan(int
u)
else
if (!co[v])
low[u] =min(low[u], dfn[v]);
}if (dfn[u] ==low[u])
ans[col] =min(ans[col], mon[st[top]]);
top--;
}return;}
void add(int
from, int
to)
intmain()
cin >>r;
for (int i = 1;i <= r; i++)
for (int i = 1;i <= n; i++)
if (!dfn[i] && mon[i] !=inf)
tarjan(i);
for (int i = 1;i <= n; i++)
if (!dfn[i])
for (int i = 1;i <= n; i++)
for (int j = head[i]; j; j =e[j].next)
if (co[i] !=co[e[j].to])
ru[co[e[j].to]]++;
int anss = 0
;
for (int i = 1;i <= col; i++)
if (!ru[i])
anss+=ans[i];
cout
<< "
yes"
<< endl << anss <
return0;
}
洛谷 P1262 間諜網路
題目描述 由於外國間諜的大量滲入,正處於高度的危機之中。如果a間諜手中掌握著關於b間諜的犯罪證據,則稱a可以揭發b。有些間諜收 賂,只要給他們一定數量的美元,他們就願意交出手中掌握的全部情報。所以,如果我們能夠收買一些間諜的話,我們就可能控制間諜網中的每一分子。因為一旦我們逮捕了乙個間諜,他手中掌握...
洛谷 P1262 間諜網路
題目描述 由於外國間諜的大量滲入,正處於高度的危機之中。如果a間諜手中掌握著關於b間諜的犯罪證據,則稱a可以揭發b。有些間諜收 賂,只要給他們一定數量的美元,他們就願意交出手中掌握的全部情報。所以,如果我們能夠收買一些間諜的話,我們就可能控制間諜網中的每一分子。因為一旦我們逮捕了乙個間諜,他手中掌握...
P1262 間諜網路
傳送門 顯然可以把所有間諜的關係建乙個圖 如果a間諜手中掌握著關於b間諜的犯罪證據,那就從a連一條邊到b 如果賄賂了乙個間諜,那麼整個聯通塊的間諜肯定都被控制 那就先把圖縮成dag 如果控制了乙個塊,那麼這個塊後面所有的塊都能被控制 為了控制所有塊,一定要賄賂沒有入度的塊,因為它不能被其它塊控制到 ...