solution:
首先這是一張有向圖,點有點權,且給定乙個起點,給定多個終點,詢問從起點出發,在任意乙個終點結束,所經過的點權和最大值
如果對於任意一條邊,把它終點的點權作為該邊的邊權,那麼只需從起點出發跑乙個最長路就可以了
但問題是,邊權都為正,一旦出現環,就無法跑最長路了
注意到一句話:「他可以經過同一路口或道路任意多次。但只要他搶劫過某個 atm 機後,該 atm 機裡面就不會再有錢了。」,這說明每個點最多只能經過一次。
這道題我們可以用強聯通分量和縮點解決
強聯通圖:對於乙個有向圖,若任意兩個節點都可以互相到達,那麼稱該圖為強連通圖
強聯通分量:對於乙個有向圖,它的「極大強聯通子圖」為強聯通分量。乙個圖可能有多個強聯通分量
縮點:對於圖的每個強聯通分量,在原圖中用乙個點表示,所形成的新圖一定是有向無環圖
於是我們就可以求出圖的強聯通分量,並縮點,再跑乙個拓撲排序或spfa,因為沒有環,所以可以跑最長路
注意縮點時要把原圖中的點的資料集中到縮完後的點上,具體的集中方法根據題目要求靈活處理
#includeusing namespace std;
//#define int long long
inline int read()
while(ch>='0'&&ch<='9')
return x*w;
}const int n=5e5+100;
int n,m,a[n],s,p,bar[n],low[n],dfn[n],c[n],d[n],barc[n],valc[n],deg[n];
int totc,tot,stk[n],ins[n],top;
vectorv[n];
struct nodee[n];
int head[n],cnt;
void add(int x,int y,int z)
void tarjan(int x)//求強聯通分量模板
} while(q.size())
} }}signed main()
for(int i=1;i<=n;++i) a[i]=read();
s=read();p=read();
for(int i=1;i<=p;++i)
for(int i=1;i<=n;++i)
for(int i=1;i<=n;++i)
for(int i=1;i<=n;++i)
}// spfa();
topu();
int ans=0;
for(int i=1;i<=totc;++i)
} cout
}
targin 強聯通分量 縮點
在乙個有向圖g中,如果兩個頂點間至少存在一條路徑,稱兩個頂點強聯通。如果所有頂點都強聯通,稱g是乙個強聯通圖。非強聯通圖有向圖的極大強聯通子圖,稱為強聯通分量。深度優先搜尋。dfn i 節點i被搜尋到的次序編號。low i i或i的子樹能夠追溯到的最早的節點的次序號。low i min dfn i ...
強連通分量 搶掠計畫
siruseri城中的道路都是單向的。不同的道路由路口連線。按照法律的規定,在每個路口都設立了乙個siruseri銀行的atm取款機。令人奇怪的是,siruseri的酒吧也都設在路口,雖然並不是每個路口都設有酒吧。banditji計畫實施siruseri有史以來最驚天動地的atm搶劫。他將從市中心出...
演算法 強連通分量縮點
有時對於乙個有向圖我們及其渴望將其變為乙個有向無環圖,這樣我們就要用到強連通分量縮點了。洛谷3387 縮點 題目背景 縮點 dp。題目描述 給定乙個 n個點 m條邊有向圖,每個點有乙個權值,求一條路徑,使路徑經過的點權值之和最大。你只需要求出這個權值和。允許多次經過一條邊或者乙個點,但是,重複經過的...