【混合】【二分】【最短路】二分最短路模型【CF】G.It is all about wisdom
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