洛谷 1948 笨笨的电话网络
2015-10-25 20:13
393 查看
题目描述 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.输入样例:
[code]5 7 1 1 2 5 3 1 4 2 4 8 3 2 3 5 2 9 3 4 7 4 5 6
输出样例:
[code]4
这题有两种做法,按出题人的想法应该是二分+spfa验证,然而因为k数值较小,可以跑一次分层图的spfa水过去233。
二分+spfa验证:
二分最少在电话线上花的钱 mid,遍历一遍边,边的权值大于mid,就把权值设为 1,其余设为 0,然后从起点跑最短路,这时到终点的最短路的意义是连接 1 到 n 需要花 dist
对超过 mid 花费的电线,显然,dist
超过 k 时二分的答案是不科学的,借这个判断就好了。
分层图:
把dist数组开成二维,利用dp的思想dist[i][j] 表示用了 j 次免费的机会到 连接到 i 点的最大值spfa松弛操作时有两种选择:用或不用免费机会 , 当然用的话一定要当前使用次数 < k 才好。
二分 + spfa验证代码:
[code]#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 > 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 == 0x3f3f3f3f) { puts("-1"); return 0; } cout<<EF(1,p); return 0; }
分层图 + spfa代码:
[code]#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 [k] >= 214748364) puts("-1"); else printf("%d",dist [k]); return 0; }
相关文章推荐
- 浏览器HTTP缓存原理分析(转)
- HTTP和FTP的区别
- 在android中使用HTTPClient以post方法发送二进制文件
- 【codevs4093】EZ的间谍网络 tarjan
- Android批量图片加载经典系列——使用二级缓存、异步网络负载形象
- 图解TCP-IP协议
- 计算机网络概述
- python学习之【16】网络编程
- 浏览器HTTP缓存原理分析
- Linux-网络配置
- TCP粘包处理 参考spserver
- 【PHPsocket编程专题(实战篇②)】兼容 Curl/Socket/Stream 的 HTTP 操作类[转]
- 编译问题:App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecur
- 网络爬虫基本原理(二)
- 网络爬虫基本原理(一)
- SmartImageView-网络图片查看器
- xcode7禁用了明文http传输的解决方法
- 使用Charles进行网络请求抓包解析
- TCP/IP传输层
- TCP/IP网络层