POJ-3662 Telephone Lines---二分+最短路+最小化第k+1大

题目链接:

https://cn.vjudge.net/problem/POJ-3662

题目大意:

求一条路径从1到n使第k+1大的边最小。

解题思路:

二分答案mid,当原边权小于等于mid新边权为0,否则新边权为1.

求最短路,若小于等于k说明满足条件
 
注意:最开始的l必须是0,而不是这些边中的最小边,因为最小化第k+1大的话答案可能为0
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<queue>
  7 #define MID(l, r) (l + (r - l) / 2)
  8 #define lson(o) (o * 2)
  9 #define rson(o) (o * 2 + 1)
 10 using namespace std;
 11 typedef long long ll;
 12 const int INF = 1e9 +7;
 13 const int maxn = 1e6 + 10;
 14 int n, m, k;
 15 struct edge{
 16     int u, v, w;
 17     edge(int u, int v, int w):u(u), v(v), w(w){}
 18     edge(){}
 19 };
 20 struct Heapnode
 21 {
 22     int d, u;
 23     Heapnode(){}
 24     Heapnode(int d, int u):d(d), u(u){}
 25     bool operator <(const Heapnode & a)const
 26     {
 27         return d > a.d;
 28     }
 29 };
 30 bool v[maxn];
 31 int d[maxn];
 32 
 33 int dijkstra(int s, int t, vector<edge>edges, vector<int>G[])
 34 {
 35     priority_queue<Heapnode>q;
 36     for(int i = 0; i <= n; i++)d[i] = INF;
 37     d[s] = 0;
 38     memset(v, 0, sizeof(v));
 39     q.push(Heapnode(0, s));
 40     while(!q.empty())
 41     {
 42         Heapnode now = q.top();
 43         q.pop();
 44         int u = now.u;
 45         if(v[u])continue;
 46         v[u] = 1;
 47         for(int i = 0; i < G[u].size(); i++)
 48         {
 49             edge& e = edges[G[u][i]];
 50             int v = e.v;
 51             if(d[v] > d[u] + e.w)
 52             {
 53                 d[v] = d[u] + e.w;
 54                 q.push(Heapnode(d[v], v));
 55             }
 56         }
 57     }
 58     return d[t];
 59 }
 60 
 61 vector<edge>edges;
 62 vector<int>G[maxn];
 63 vector<edge>edges2;
 64 void addedge(int u, int v, int w)
 65 {
 66     edges.push_back(edge(u, v, w));
 67     int m = edges.size();
 68     G[u].push_back(m - 1);
 69 }
 70 void init(int mid)
 71 {
 72     edges2.clear();
 73     for(int i = 0; i < edges.size(); i++)
 74     {
 75         edge& e = edges[i];
 76         if(e.w <= mid)
 77         {
 78             edges2.push_back(edge(e.u, e.v, 0));
 79         }
 80         else
 81         {
 82             edges2.push_back(edge(e.u, e.v, 1));
 83         }
 84     }
 85 }
 86 int main()
 87 {
 88     scanf("%d%d%d", &n, &m, &k);
 89     int l = 0, r = 0, u, v, w;
 90     while(m--)
 91     {
 92         scanf("%d%d%d", &u, &v, &w);
 93         addedge(u, v, w);
 94         addedge(v, u, w);
 95         r = max(r, w);
 96     }
 97     int ans = -1;
 98     while(l <= r)//l最开始要设置成0,不能设置成最小边,因为第k大可能为0
 99     {
100         int mid = (l + r) / 2;
101         init(mid);
102         int t = dijkstra(1, n, edges2, G);
103         //cout<<mid<<" "<<t<<endl;
104         if(t <= k)
105         {
106             ans = mid;
107             r = mid - 1;
108         }
109         else
110         {
111             l = mid + 1;
112         }
113     }
114     cout<<ans<<endl;
115     return 0;
116 }

 

转载于:https://www.cnblogs.com/fzl194/p/9028319.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值