二分最短路模型——G.It is all about wisdom
阿新 • • 發佈:2021-08-05
Mixed——二分最短路模型——G.It is all about wisdom
考時bfs,dfs加剪枝(dfs在最壞情況下的剪枝相當於bfs加剪枝,其實bfs加剪枝,有點奇怪,一些剪枝在bfs的作用下並不能發揮很好的效果),在第二點的時候都t了,對於至少這類問題應該從二分的角度出發,而不是用求穩的思想,每一個點,每一條路都大概率地去嘗試。(二分的check是有一定的原則去辦事情,而普通的找是以相對弱的原則來辦事情)
思路:二分是為了迅速找到一個值(智商值),如果能夠以這個智商值過了就過了(最短路是為了儘可能壓縮金錢的消耗,看一下最小花費會不會小於身上帶的錢),並且還要儘可能逼近最優的智商值。
二分
-
目的:為了從眾多的可能的答案中快速找到最優答案,節省時間,如果有遇到time limited 的情況,可以考慮一下使用二分的寫法
換種角度來思考什麼叫做可能的答案,可能的答案,它的答案是一個範圍,比如說至少,比如說至多,嚴格小於,less than.....
-
二分的前提:單調性
-
內容:
-
check函式
(把最短路的演算法融進來)
-
邊界的寫法
-
bool check()
{
if(條件) return true;
return false;
}
- 二分模板
while(l<=r) { mid = l+(r-l)>>1; if(check(mid)) r=r-1,ans=r;//趁機保留答案 else l=l+1; }
最短路
int dijkstra(int st,int ed,int 二分嘗試的點) { 小根堆 使用情況的使用陣列 將起點壓入小根堆 while(heap.size()) { 提取 將提取出的結點的使用情況標記為已使用 for 掃描提取出來的點的周圍的所有邊 特殊情況 continue 路徑更不上時代 continue 鬆弛操作 } 因為是二分,判斷一下dist[ed]和二分嘗試的點的關係,再看一下要return什麼 }
程式碼
#include<bits/stdc++.h>
using namespace std;
const int N = 1E5+10,M = 2E5+10,INF = 0x3f3f3f3f;
typedef pair<int,int > PII;
int h[N],e[M],ne[M],w[M],limit[M],idx;
int n,m,cost;
void add(int a,int b,int c,int d)
{
e[idx]=b,ne[idx]=h[a],w[idx]=c,limit[idx]=d,h[a]=idx++;
}
bool check(int x)
{
int dist[n+1];//用dijkstra演算法找到最小花費
bool used[n+1];
memset(dist,0x3f,sizeof(dist));
memset(used,false,sizeof(used));
priority_queue<PII,vector<PII>,greater<PII> > heap;
heap.push(PII{0,1});
while(heap.size())
{
PII t = heap.top();
heap.pop();
int d = t.first,u = t.second;
if(used[u])continue;
used[u]=true;
for(int i=h[u];~i;i=ne[i])
{
int j = e[i];
if(limit[i]>x||d+w[i]>cost)continue;//沒有資格進入途徑
if(dist[j]>d+w[i])
{
dist[j]=d+w[i];
heap.push(PII(dist[j],j));
}
}
}
if(dist[n]<cost) return true;
return false;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int l=0,r=0,mid;
scanf("%d%d%d",&n,&m,&cost);
memset(h,-1,sizeof(h));
idx=0;//記得歸零
for(int i=0;i<m;i++)
{
int aa,bb,mon,wis;
cin>>aa>>bb>>mon>>wis;
add(aa,bb,mon,wis);add(bb,aa,mon,wis);
r=max(r,wis);
}
int ans=-1;
while(l<=r)
{
mid = l + (r-l)/2;
if(check(mid))
ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans<<endl;
}
return 0;
}
其他
- 在使用鏈式前向星的寫法的時候,不單要把h陣列重新設定為-1,也要把idx歸零(在處理多組資料的時候).
- 無向邊記得乘2