洛谷 1948 笨笨的电话网络
来源:互联网 发布:ipad翻墙用什么软件 编辑:程序博客网 时间:2024/05/27 16:42
题目描述 Description
多年以后,笨笨长大了,成为了电话线布置师。由于地震使得某市的电话线全部损坏,笨笨是负责接到震中市的负责人。该市周围分布着N(1<=N<=1000)根据1……n顺序编号的废弃的电话线杆,任意两根线杆之间没有电话线连接,一共有p(1<=p<=10000)对电话杆可以拉电话线。其他的由于地震使得无法连接。
第i对电线杆的两个端点分别是ai,bi,它们的距离为li(1<=li<=1000000)。数据中每对(ai,bi)只出现一次。编号为1的电话杆已经接入了全国的电话网络,整个市的电话线全都连到了编号N的电话线杆上。也就是说,笨笨的任务仅仅是找一条将1号和N号电线杆连起来的路径,其余的电话杆并不一定要连入电话网络。
电信公司决定支援灾区免费为此市连接k对由笨笨指定的电话线杆,对于此外的那些电话线,需要为它们付费,总费用决定于其中最长的电话线的长度(每根电话线仅连接一对电话线杆)。如果需要连接的电话线杆不超过k对,那么支出为0.
请你计算一下,将电话线引导震中市最少需要在电话线上花多少钱?
输入格式:
输入文件的第一行包含三个数字n,p,k;
第二行到第p+1行,每行分别都为三个整数ai,bi,li。
输出格式:
一个整数,表示该项工程的最小支出,如果不可能完成则输出-1.
输入样例:
5 7 11 2 53 1 42 4 83 2 35 2 93 4 74 5 6
输出样例:
4
这题有两种做法,按出题人的想法应该是二分+spfa验证,然而因为k数值较小,可以跑一次分层图的spfa水过去233。
二分+spfa验证:
二分最少在电话线上花的钱 mid,遍历一遍边,边的权值大于mid,就把权值设为 1,其余设为 0,然后从起点跑最短路,这时到终点的最短路的意义是连接 1 到 n 需要花 dist[n] 对超过 mid 花费的电线,显然,dist[n] 超过 k 时二分的答案是不科学的,借这个判断就好了。
分层图:
把dist数组开成二维,利用dp的思想dist[i][j] 表示用了 j 次免费的机会到 连接到 i 点的最大值spfa松弛操作时有两种选择:用或不用免费机会 , 当然用的话一定要当前使用次数 < k 才好。
二分 + spfa验证代码:
#include<iostream>#include<cstdio>#include<queue>#include<cstring>#include<algorithm>using namespace std;const int size = 200010;int head[size],next[size],dist[size];bool use[size];int dis[size],rr[size];int n,p,k;struct dc{ int t,d;} l[size];int tot = 1;void build(int f,int t,int d){ l[tot].t = t; l[tot].d = d; next[tot] = head[f]; head[f] = tot ++;}queue < int > q;void spfa(){ memset(dist,63,sizeof(dist)); dist[1] = 0; use[1] = 1; q.push(1); while(!q.empty()) { int f = q.front(); q.pop(); use[f] = 0; for(int i = head[f] ; i ; i = next[i]) { int t = l[i].t; if(dist[t] > dist[f] + dis[i]) { dist[t] = dist[f] + dis[i]; if(!use[t]) { use[t] = 1; q.push(t); } } } }}bool check(int mid){ for(int i = 1 ; i < tot ; i ++) if(l[i].d > mid) dis[i] = 1; else dis[i] = 0; spfa(); if(dist[n] > k) return false; return true;}int EF(int l,int r){ while(r - l > 1) { int mid = (l + r) >> 1; if(!check(rr[mid])) l = mid; else r = mid; } return rr[r];}int main(){ scanf("%d%d%d",&n,&p,&k); for(int i = 1 ; i <= p ; i ++) { int f,t,d; scanf("%d%d%d",&f,&t,&d); build(f,t,d); build(t,f,d); rr[i] = d; } sort(rr+1,rr+p+1); spfa(); if(dist[n] == 0x3f3f3f3f) { puts("-1"); return 0; } cout<<EF(1,p); return 0;}
分层图 + spfa代码:
#include<iostream>#include<cstdio>#include<queue>using namespace std;const int size = 20010;int head[size],next[size],dist[size][11];bool use[size][11];int n,m,k;int tot = 1;queue < int > q;struct dc{ int t,d;}l[size];void build(int f,int t,int d){ l[tot].t = t; l[tot].d = d; next[tot] = head[f]; head[f] = tot ++;}void spfa(){ for(int i = 1 ; i <= n ; i ++) for(int j = 0 ; j <= k ; j ++) dist[i][j] = 214748364; dist[1][0] = 0; use[1][0] = 1; q.push(1); q.push(0); while(!q.empty()) { int f = q.front(); q.pop(); int time = q.front(); q.pop(); use[f][time] = 0; for(int i = head[f] ; i ; i = next[i]) { int t = l[i].t; if(dist[t][time] > max(dist[f][time],l[i].d)) //dist[t][time] > max(dist[f][time],l[i].d) { dist[t][time] = max(dist[f][time],l[i].d); if(!use[t][time]) { use[t][time] = 1; q.push(t); q.push(time); } } if(time < k) { if(dist[t][time+1] > dist[f][time]) { dist[t][time+1] = dist[f][time]; if(!use[t][time+1]) { use[t][time+1] = 1; q.push(t); q.push(time+1); } } } } }}int main(){ scanf("%d%d%d",&n,&m,&k); for(int i = 1 ; i <= m ; i ++) { int f,t,d; scanf("%d%d%d",&f,&t,&d); build(f,t,d); build(t,f,d); } spfa(); if(dist[n][k] >= 214748364) puts("-1"); else printf("%d",dist[n][k]); return 0;}
- 洛谷 1948 笨笨的电话网络
- 2014.7.8模拟赛【笨笨的电话网络】
- TelephonyManager电话网络信息的服务类
- 电话网络(phone)
- 公共交换电话网络
- HYSBZ 1596 电话网络
- 【二分】电话网络
- 电话网络 CODEVS
- 很有意思的网络通信例子---小明与电话
- 电话网络中的常用术语
- 电话网络相关PBX,ICT
- PSTN 公共交换电话网络
- VoIP和电话网络浅析
- android sip 网络 ip 电话
- [BZOJ1596] [Usaco2008 Jan]电话网络
- bzoj1596 [Usaco2008 Jan]电话网络
- 【bzoj1596】[Usaco2008 Jan]电话网络
- 1596: [Usaco2008 Jan]电话网络
- 一个FTP任务
- 用JS获取地址栏参数的方法(超级简单)
- POJ 1789 Truck History (Prim)
- webview简单加载页面
- 程序员编程面试取胜的8个技巧
- 洛谷 1948 笨笨的电话网络
- 什么是shell?
- IO输入输出流
- 第八周周总结
- iOS 16进制转成汉字
- Leetcode || Palindrome Number
- 软件测试缺陷报告的5c标准
- 网络必须首先了解的基本知识
- JAVA中的多线程