标签:二分 pq dist dij int 边权 路径 edges 340
【图论+二分答案】【二分dij】340. 通信线路
题意:
设置一个关于边权的阈值,选择一条从起点到终点的路径,这条路径上的每一条边都有一个边权,这条路径可以最多选择k条路径来进行关闭边权的操作,使得这些边权最终没有统计到路径的和中,从而求一个这样子最小的和。
从贪心的角度:
首先要选择不重复走的路径。
其次k条路要选择这条路径上前k大的路径。也就是实际花费变成了第k+1大的路。也就是要去找到一条路径,且这条路径在所有可行的路径中的第k+1边边权最小。
而不妨设第k+1大边的边权为w,那么前k条边的权值是都是大于w,也就是整条路径上大于w的条数为k。
所以我们不妨可以通过二分答案w,同时以w重新定义边权,如果边权大于w,则边权设置为1,否则设置成0,然后去跑关于新生成的图的最短路。
思路分析:
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f;
#define PII pair<int,int>
#define mp(x,y) make_pair(x,y)
#define FI first
#define SE second
using namespace std;
const int N = 1E3+100, M = 2E4+100;
struct edge{
int u,v,w,nxt;
}edges[M];
int idx,h[N];
void add(int u,int v,int w)
{
edges[idx] = {u,v,w,h[u]};
h[u] = idx++;
}
int dist[N],used[N],n,p,k;
bool dij(int jud)
{
memset(dist,0x3f,sizeof(dist));
memset(used,0,sizeof(used));
priority_queue<PII,vector<PII>,greater<PII>> pq;
dist[1] = 0;
pq.push({0,1});
while(pq.size())
{
PII t = pq.top();
pq.pop();
int d = t.FI,u = t.SE;
if(d>dist[u]||used[u]) continue;
used[u] = true;
for(int i = h[u];~i;i=edges[i].nxt)
{
int v = edges[i].v;
if(dist[v]>d+(edges[i].w>jud?1:0))
{
dist[v] = d + (edges[i].w>jud?1:0);
pq.push({dist[v],v});
}
}
}
return dist[n]<=k;
}
int main()
{
memset(h,-1,sizeof(h));
scanf("%d%d%d",&n,&p,&k);
for(int i=1;i<=p;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);add(v,u,w);
}
int l = 0 ,r = 1e6+50,ans;
while(l<=r)
{
int mid = l + r >>1;
//cout<<l<<" "<<r<<" "<<mid<<endl;
if(dij(mid))
{
ans = mid;
r = mid-1;
}
else l = mid+1;
}
if(r!=1e6+50)
cout<<ans;
else cout<<-1;
return 0;
}
标签:二分,pq,dist,dij,int,边权,路径,edges,340 来源: https://www.cnblogs.com/BeautifulWater/p/15557878.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。