pre芝士\(of\)
\(tarjan\),下方也有引用的:\(\text\)
題目給了你乙個有向圖,乙個有環,而且只有部分點有點權,部分點沒有的乙個有向圖。你現在使用點\(n\)點權值大小的代價可以進行:將這個點以及這個點可以到達的所有點放入點集\(\mathbf e\)中的操作,保證在點集\(\mathbf e\)中的所有點能到達的點也都在\(\mathbf e\)。
如果\[a \rightarrow b
\]\[a \in \mathbf e
\]則保證
\[b \in \mathbf e
\]那麼問將所有點放入點集\(\mathbf e\)的最小代價是多少。如果不能輸出\(\text\)以及無法放入的點中最小的那個,可以則輸出\(\text\) & 最小代價。
我們先對題目細節進行分析:
首先是有向圖。
如果\(a\)可以購買,\(a\)可以到\(b\),那麼花費\(value_a\)可以使得\(\left\ \subseteq \mathbf e\),可是不保證買下\(b\)就有\(a\)或者說b可能根本無法單獨獲取。
那麼很顯然我們不能點對點分析了,這樣不能保證獲得最小代價也不能保證複雜度優秀。
既然不能點對點分析,我們就考慮對於這題圖的特性。
首先我會想到跑類似點權最短路的東西,但是似乎無法實現,因為如果存在不可到達的點,並不能很好判斷,而且在跑最短路時我們如果將沒有點權的點貪心為0,那麼無法繼續程式。稍微改下思路,這樣反而變成乙個裸的dfs,複雜度與實現難度變得奇奇怪怪。
不過既然想到所謂點權最短路,那麼我們就可以考慮到,對於點權最短路,我們必須考慮是否\(\text\),不是\(\text\)就不能完美實現記憶化搜尋等點權計算的操作。畢竟點不是有向邊,對於點來說很可能會陷入死迴圈。
結合以上資訊,我們突然想到乙個模板涵蓋以上特點:p3387 【模板】縮點。
還沒學\(tarjan\)的同學,歡迎來踩\(\text\)
如果我們對這題進行縮點,大部分問題就迎刃而解。
對於這個題,縮點後的處理才是更為精髓的部分。我寫這篇題解其實是因為對於我自己的做法,我很吃驚居然ac了,先縮點,縮點時記得記錄這個強連通分量內最便宜的那個,如果沒有能買的也要記錄一下「-1」為不能買的。
我在縮完點後,乾脆對每乙個點做dfs,能走的點盡量走,dfs時順便記憶化該點是否走過,如果走過則不再dfs。就直接從第乙個點開始列舉,判斷2點:1是是否有能購買的,沒有你dfs也沒用,有的話還要看之前的點是否涵蓋他了。
這個很離譜對吧,真的很離譜,因為他是錯的,他只有\(92pts\)
(就這還92啊)
對於這種情況,很明顯只需要買2就只需\(val=4\)一石二鳥,但我for迴圈從1開始dfs我就會先買1在買2導致\(val=7\)。
然後我想了想。。。想了想。我想到可以換每個點都做一次起點,但那樣貌似t了。
然後我常識性地把他倒著迴圈了一遍然後再做,取最小的那個。
就a了。所以就驚了並且摸了(指不再深究)。
\(\text\)的情況詳見**。
#include#include#include#include#include#include#include#define n 300005
using namespace std;
int n,p,r;
int val[n],dfn[n],low[n],tot,cnt,sec[n],secs,size[n],head[n],rtsec[n],head1[n],x[n],y[n];
int ans;
stack s;
bool in[n],oksec[n];
struct rey
e[1000005],e1[1000005];
void add(int u,int v)
void add1(int u,int v)
void tarjan(int x)
else if(in[go])low[x]=min(low[x],dfn[go]);
} if(dfn[x]==low[x])
while(x!=tp);
}}//tarjan縮點模板,詳見另一篇學習筆記。
void dfs(int u)
}//dfs一直走並記錄走過的。
int main()
scanf("%d",&r);
for(int i=1;i<=r;i++)
for(int i=1;i<=n;i++)
cnt=0;
for(int i=1;i<=r;i++)
//縮點完也要重新建圖,因為縮點後雖然沒有環或者強聯通分量,
//但是存在買整個強連通分量同時獲得另乙個的情況。
} for(int i=1;i<=secs;i++)
//dfs
} bool ok=1;
int outw=n+1;
for(int i=1;i<=secs;i++)
//仍然沒走的就一定是no
for(int j=1;j<=n;j++)}}
} if(ok==0)
int tmp=ans;
ans=0;
memset(oksec,0,sizeof(oksec));
for(int i=secs;i>=1;i--)
}//倒著來一遍
ans=min(ans,tmp);
printf("yes\n%d\n",ans);
return 0;
}
可能是資料比較水,如果有大佬可以hack掉我會很感激並優化題解和**。 P1262 間諜網路
傳送門 顯然可以把所有間諜的關係建乙個圖 如果a間諜手中掌握著關於b間諜的犯罪證據,那就從a連一條邊到b 如果賄賂了乙個間諜,那麼整個聯通塊的間諜肯定都被控制 那就先把圖縮成dag 如果控制了乙個塊,那麼這個塊後面所有的塊都能被控制 為了控制所有塊,一定要賄賂沒有入度的塊,因為它不能被其它塊控制到 ...
洛谷 P1262 間諜網路
題目描述 由於外國間諜的大量滲入,正處於高度的危機之中。如果a間諜手中掌握著關於b間諜的犯罪證據,則稱a可以揭發b。有些間諜收 賂,只要給他們一定數量的美元,他們就願意交出手中掌握的全部情報。所以,如果我們能夠收買一些間諜的話,我們就可能控制間諜網中的每一分子。因為一旦我們逮捕了乙個間諜,他手中掌握...
洛谷 P1262 間諜網路
題目描述 由於外國間諜的大量滲入,正處於高度的危機之中。如果a間諜手中掌握著關於b間諜的犯罪證據,則稱a可以揭發b。有些間諜收 賂,只要給他們一定數量的美元,他們就願意交出手中掌握的全部情報。所以,如果我們能夠收買一些間諜的話,我們就可能控制間諜網中的每一分子。因為一旦我們逮捕了乙個間諜,他手中掌握...