一眼二分。。。然后就没思路了。。。
- 二分当前路径上第\(k+1\)大的边权,要求最小化第\(k+1\)大的边权,故考虑二分。
- 二分的判定条件是当前路径上边权比\(mid\)大的边数应不超过\(k\)条
于是现在核心问题是如何当前二分的值为\(mid\)的情况下,是否存在一条从\(1\)到\(n\)的路径,边权大于\(mid\)的边数不超过\(k\)
问题转化如下:
- 将大于\(mid\)的边权赋为\(1\),小于等于\(mid\)的边权赋为\(0\)
- 根据贪心思想,我们在新图上求一遍最短路,若\(dist[n] <= k\),说明存在一条从\(1\)到\(n\)的路径,边权大于\(mid\)的边数不超过\(k\),反之不存在
而最短路的求法可采用\(0-1 BFS\)
注意:二分有边界向右多取一个,据此判断无解情况
const int N=1010;
vector<PII> g[N];
int dist[N];
bool vis[N];
int n,m,k;
int check(int mid)
{
memset(dist,0x3f,sizeof dist);
memset(vis,0,sizeof vis);
deque<int> q;
dist[1]=0;
q.push_back(1);
while(q.size())
{
int t=q.front();
q.pop_front();
if(t == n) return dist[t];
if(vis[t]) continue;
vis[t]=true;
for(int i=0;i<g[t].size();i++)
{
int j=g[t][i].fi,w=(g[t][i].se>mid);
if(dist[j] > dist[t] + w)
{
dist[j]=dist[t]+w;
if(!w) q.push_front(j);
else q.push_back(j);
}
}
}
return INF;//1到n不连通
}
int main()
{
cin>>n>>m>>k;
int l=0,r=0;
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
g[a].pb({b,c});
g[b].pb({a,c});
r=max(r,c);
}
int tr=r;
r++;
while(l<r)
{
int mid=l+r>>1;
if(check(mid)<=k) r=mid;
else l=mid+1;
}
if(r == tr+1) puts("-1");
else cout<<l<<endl;
//system("pause");
}
分层图解法
- 最大边尽量小
const int N=1010;
struct Node
{
int dis,u,cnt;
bool operator>(const Node &W) const
{
return dis>W.dis;
}
};
vector<PII> g[N];
int dist[N][N];
bool vis[N][N];
int n,m,k;
void dijkstra()
{
memset(dist,0x3f,sizeof dist);
priority_queue<Node,vector<Node>,greater<Node> > heap;
dist[1][0]=0;
heap.push({0,1,0});
while(heap.size())
{
int t=heap.top().u,c=heap.top().cnt;
heap.pop();
if(vis[t][c]) continue;
vis[t][c]=true;
for(int i=0;i<g[t].size();i++)
{
int j=g[t][i].fi,w=g[t][i].se;
if(c+1<=k && dist[j][c+1]>dist[t][c])
{
dist[j][c+1]=dist[t][c];
heap.push({dist[j][c+1],j,c+1});
}
if(dist[j][c]>max(dist[t][c],w))
{
dist[j][c]=max(dist[t][c],w);
heap.push({dist[j][c],j,c});
}
}
}
}
int main()
{
cin>>n>>m>>k;
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
g[a].pb({b,c});
g[b].pb({a,c});
}
dijkstra();
int res=INF;
for(int i=0;i<=k;i++) res=min(res,dist[n][i]);
if(res == INF) puts("-1");
else cout<<res<<endl;
//system("pause");
}