CH 6703 PKU ACM Team's Excursion 有向圖的必經邊或“橋”
title
CH 6703 PKU ACM Team’s Excursion
總時間限制: 2000ms 記憶體限制: 65536kB
描述
It is a traditional activity for PKU ACM Team to go hiking during the summer training camp. However, this tradition has been abandoned for several years. To recover this meaningful and interesting hiking tradition, the coach is planning an excursion for this summer. In addition, the new team members strongly urged the team somewhere “exciting”. To satisfy their desire, the coach has found a national park and acquired the map of this park. In this map, there are n intersections (numbered from 0 to n-1) connected by m one-way roads. This map has an interesting property that you cannot go back to the intersection you stand now once you leave it. Thus, the map of the park is a typical directed acyclic graph!
So, why is this place exciting? Because some of the roads called “bridges” (they are not true bridges but a jargon referred to the special roads we will soon define below) are dangerous because the bridges may collapse when we walk along them. Don’t panic! The safety facilities are adequate and robust, and there is only mentally impact without physical danger. Just have fun!
The excursion will begin at a certain starting intersection s and end at a certain destination intersection t. You can find a route from intersection s to t. A road is called a “bridge” if and only if you cannot find a route from starting intersection to destination once it disappears. The other ordinary roads are not bridges so they are not dangerous at all. According to the experience of the tourists, the danger level of a “bridge” is equal to its length.
Some wicked guys want to make the excursion more dangerous. But wait! A girl is crying! What? A girl? Eventually, PKU ACM team recruited a girl this year! OK… Lady first is a long term policy in PKU ACM team. Boys and girls finally reach a compromise that the excursion should be as safe as possible.
The national park provides an “express” service. The hikers can order at most two buses beforehand to help them to escape some of the most dangerous routes. Each bus can start from anywhere (any intersection or any point on any road) in the national park. But the bus is powered by electricity so it can only travel no more than q meters continuously and the passenger should get off before the electricity runs out. Simply speaking, the team can choose two “express” routes (each starts from anywhere and ends at anywhere), neither of the two routes is more than q meters. When the team is on a bus, the danger level along the route can be ignored.
The problem is reduced to find a route from the start intersection to the end with the least sum of danger levels. On the way we can take two special buses to make our route safe. The routes of two buses can start from anywhere and end at anywhere but the whole team should be put into one bus at one time. Individual activity is forbidden.
輸入
The first line contains an integer T (1 ≤ T ≤ 10) – the number of test cases.
For each test case:
The first line contains five integers n, m, s, t and q (1 ≤ n ≤ 100 000, 1 ≤ m ≤ 200 000, 0 ≤ s,t < n, s ≠ t, 1 ≤ q ≤ 1 000 000 000), indicate the number of intersections, the number of roads, the starting intersection, the end intersection and the limited length of route of a single bus can travel respectively.
The next m lines have the information of all roads in the directed acyclic graph. Each line contains a triple (u,v,w) indicating a road from intersection u to intersection v with length w (1 ≤ w ≤ 1 000) meters.
輸出
For each test case, please output a single line containing an integer representing the total danger level of the optimal route. If there is no route from s to t, output “-1” instead.
樣例輸入
1
8 9 0 7 7
0 4 1
0 1 10
1 2 9
4 2 2
2 5 8
4 3 3
5 6 6
5 6 7
6 7 5
樣例輸出
1
analysis
做了這道題後,我才正式發現:有向圖也是有“橋”的,只不過定義不一樣罷了。
放定義:若從到的每條路徑都經過一條邊,則稱這條邊是有向圖中從到的必經邊或“橋”。
所以說,學東西還是學全面點的,否則就會像我一樣出現很尷尬的事。。。。。。qwq
好了,說點有用的,大家可以看到,有向圖的“橋”和無向圖的橋,概念不一樣,那應該也能猜到兩個的演算法會不太一樣,據《算階》上說:
“有向圖的必經點和必經邊是一個較難的問題。因為環上的點也可能是必經點,所以不能簡單地把強連通分量縮點後按照有向無環圖()來處理。演算法通過計算,能夠在的時間內求出從有向圖的指定起點出發,走到每個點的必經點集。這超出了我們的討論範圍,感興趣的讀者可以閱讀本書作者在全國資訊學奧林匹克競賽冬令營上的講義《圖連通性若干擴充問題探討》。”
不過,值得一提的是,我們有很簡單的方法計算有向無環圖(DAG)的必經點和必經邊:
1.在原圖中按照拓撲序進行動態規劃,求出起點到圖中每個點的路徑條數。
2.在反圖上再次按照拓撲序進行動態規劃,求出每個點到終點的路徑條數。
顯然,表示從到的路徑總條數。根據乘法原理:
1.對於一條有向邊,若,則是有從到的必經邊。
2.對於一個點,若,則是從到的必經點。
路徑條數是一個指數級別的整數,通常超過了32位或64位整數的表示範圍。受思想的啟發,我們可以把路徑條數對一個大指數取模後再儲存到與陣列中。這樣帶來的後果是有較小的概率會產生誤判。保險起見,若題目時限寬鬆,我們多選取幾個質數,分別作為模數進行計算。
ok,介紹完了這個知識點,就可以來看看這道題了(不要想著看程式碼,快200行哩,不理解的話,可能。。。。。。。。。)。
現,摘錄一下《算階》上的題解。
首先,用前面提到的計算路徑條數(並取模)的方法,求出從到的所有“橋”。
根據貪心策略,因為“橋”是從到的任意一條路徑都包含的邊,所以我們應該讓路徑上除了“橋”以外的部分儘量短。並且我們只關心長度,不關心“橋”以外的部分到底是哪些邊。所以我們可以求出從到的任意一條最短路,考慮在這條最短路徑的什麼地方叫車,能使危險程度最小。
一條最短路其實就是一條“鏈”,我們要用兩個區間覆蓋鏈上兩段長度不超過的部分,使未被覆蓋的“橋”的長度之和最小。
如果只有一個區間,那麼是非常好做的。可以正著掃描一遍這條最短路,用動態規劃演算法求出,表示從到最短路上的第個節點,只打一次車的最小危險程度。
類似地,還可以倒著掃描一遍,用動態規劃演算法求出,表示從最短路上的第個節點到,只打一次車的最小危險程度。
最後,我們列舉“切點”,用更新答案即可。
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=3e5+10,maxm=2e5+5;
const ll inf=0x7fffffff;
const ll mod=1e9+7;
template<typename T>inline void read(T &x)
{
x=0;
T f=1,ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
ll spot[maxm<<1],ver[maxm<<1],edge[maxm<<1],Next[maxm<<1],head[maxn],Out[maxn],len;
inline void add(ll x,ll y,ll z)
{
spot[++len]=x,ver[len]=y,edge[len]=z,Next[len]=head[x],head[x]=len,++Out[y];
}
ll vc[maxm<<1],ec[maxm<<1],Nc[maxm<<1],hc[maxn],Otc[maxn],lc;
inline void addc(ll x,ll y,ll z)
{
vc[++lc]=y,ec[lc]=z,Nc[lc]=hc[x],hc[x]=lc,++Otc[y];
}
ll n,m,s,t,q;
ll deg[maxn],fs[maxn];
inline void topsort1()
{
memcpy(deg,Out,sizeof(Out));
queue<ll>q;
fs[s]=1;
for (ll i=1;i<=n;++i)
if (!deg[i])
q.push(i);
while (!q.empty())
{
ll x=q.front();
q.pop();
for (ll i=head[x];i;i=Next[i])
{
ll y=ver[i];
fs[y]+=fs[x];
fs[y]%=mod;
if (!--deg[y]) q.push(y);
}
}
}
ll ft[maxn];
inline void topsort2()
{
queue<ll>q;
ft[t]=1;
for (ll i=1;i<=n;++i)
if (!Otc[i])
q.push(i);
while (!q.empty())
{
ll x=q.front();
q.pop();
for (ll i=hc[x];i;i=Nc[i])
{
ll y=vc[i];
ft[y]+=ft[x];
ft[y]%=mod;
if (!--Otc[y]) q.push(y);
}
}
}
ll dist[maxn],pre[maxn];
inline void topsort3()
{
queue<ll>q;
for (ll i=1;i<=n;++i)
if (!Out[i])
q.push(i);
while (!q.empty())
{
ll x=q.front();
q.pop();
for (ll i=head[x];i;i=Next[i])
{
ll y=ver[i],z=edge[i];
if (dist[y]>dist[x]+z)
{
dist[y]=dist[x]+z;
pre[y]=x;
}
if (!--Out[y]) q.push(y);
}
}
}
ll f[maxn],path[maxn],sum[maxn],cnt;
bool flag1[maxn];
inline void solve1()
{
ll cur=1;
for (ll i=1;i<=cnt;++i)
{
while (dist[path[i]]-dist[path[cur]]>q)
++cur;
f[i]=f[i-1];
ll temp=sum[path[i]]-sum[path[cur]];
if (flag1[path[cur]])
temp+=q-(dist[path[i]]-dist[path[cur]]);
f[i]=max(f[i],temp);
}
}
ll g[maxn];
bool flag2[maxn];
inline void solve2()
{
ll cur=cnt;
for (ll i=cnt;i>=1;--i)
{
while (dist[path[cur]]-dist[path[i]]>q)
--cur;
g[i]=g[i+1];
ll temp=sum[path[cur]]-sum[path[i]];
if (flag2[path[cur]])
temp+=q-(dist[path[cur]]-dist[path[i]]);
g[i]=max(g[i],temp);
}
}
inline void Clear()
{
for (ll i=1;i<=n;++i)
dist[i]=inf;
memset(fs,0,sizeof(fs));
memset(ft,0,sizeof(ft));
memset(flag1,0,sizeof(flag1));
memset(flag2,0,sizeof(flag2));
memset(sum,0,sizeof(sum));
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
memset(head,0,sizeof(head));
memset(hc,0,sizeof(hc));
len=lc=0;
}
int main()
{
int T;read(T);
while (T--)
{
read(n);read(m);read(s);read(t);read(q);
++s,++t;
Clear();
for (ll i=1;i<=m;++i)
{
ll x,y,z;
read(x);read(y);read(z);
++x,++y;
add(x,y,z);addc(y,x,z);
}
topsort1();
topsort2();
for (ll i=1;i<=len;++i)
{
ll x=spot[i],y=ver[i];
if (fs[x]*ft[y]%mod==fs[t])
{
sum[y]=edge[i];
flag1[y]=flag2[x]=1;
}
}
dist[s]=0;
topsort3();
if (dist[t]==inf)
puts("-1");
else
{
cnt=0;
ll p=t;
do
{
path[++cnt]=p;
p=pre[p];
} while (p!=s);
path[++cnt]=s;
reverse(path+1,path+cnt+1);
for (ll i=1;i<=cnt;++i)
sum[path[i]]+=sum[path[i-1]];
solve1();
solve2();
ll temp=sum[path[cnt]],ans=inf;
for (ll i=1;i<=cnt;++i)
ans=min(ans,temp-(f[i]+g[i]));
printf("%lld\n",ans);
}
}
return 0;
}
相關文章
- 圖論-有向圖縮點圖論
- 博弈論進階之樹的刪邊遊戲與無向圖的刪邊遊戲遊戲
- 有向圖的強連通性(java)Java
- 有向圖的拓撲排序——DFS排序
- ST's Ch02 修改Oracle User Process。Oracle
- 有向圖的連通性(判強連通)
- Tarjan 求有向圖的強連通分量
- pku 1141 Brackets SequenceRacket
- pku 1160 Post Office
- NYNU ACM 藍橋杯選拔賽 解題報告ACM
- ST 's Ch01 Oracle常識及常用SQLOracleSQL
- 有向圖的基本演算法-Java實現演算法Java
- 帶回路的有向圖採用什麼模式?模式
- iPhone 7s或配無邊框OLED螢幕 僅限大屏版iPhone
- 用SQL解決有向圖問題SQL
- 軟考筆記-有向圖的鄰接矩陣筆記矩陣
- iPhone 6s或配Force Touch 沒有雙鏡頭iPhone
- 學習java的路線圖-五個必經階段Java
- hdu4280 網路流+掛(無向圖的網路流注意建邊)
- 設計師必須向產品經理學習的四個技能點
- 北美KubeCon新風,正把K8S魔力帶向邊緣計算K8S
- 用SQL解決有向圖問題(轉)SQL
- 拓撲排序 (BFS )DAG (有向無環圖)排序
- ch5 資訊不對稱與資訊經濟H5
- 求有向圖的強連通分量(c語言版)C語言
- 當物聯網遇上雲原生:K8s向邊緣計算滲透中K8S
- PMInterview產品經理精英訪談錄4—— HP China +Design Team 設計總監向怡寧View
- 最小樹形圖(有向圖的最小生成樹)朱劉演算法演算法
- 圖論-BFS解無權有向圖最短路徑距離圖論
- UVA 10859 有向無環圖的動態規劃動態規劃
- Python修改柱狀圖邊緣柱子與圖邊界的距離Python
- 藍橋杯ACM簡單題-交換瓶子 2020-12-22ACM
- [Java] 藍橋杯ADV-209 演算法提高 c++_ch02_04Java演算法C++
- [書呆子]值得看的流水賬——《ACM圖靈獎》ACM圖靈
- FPGA:AI ASIC的必經之路?FPGAAI
- 某人的ACM經歷 (真的很好 - 適合我的水平看)ACM
- CH57X/CH58X/CH59X 加PA應用H5
- Java學習路線圖,其五個必經階段Java