Dual-SIM Phone
2015-08-26 20:29
330 查看
题意
nn个运营商,每个运营商可以发送短信给其他的一些运营商。彼得可以选两个运营商,通过两个运营商中花钱更少的一个发送短信给运营商。帮助彼得选择一对运营商,使得他能够发送短信给所有运营商,而且发送短信的最大费用最小。n≤104n\le 10^4
运营商能发送短信的关系数k≤105k\le 10^5
TimeTime Limits:2000msLimits:2000ms
MemoryMemory Limits:64MLimits:64M
分析
这题其实就是暴力优化。考虑二分答案。用bitsetbitset记录一个运营商ii在当前答案限制下能发给的运营商的集合SiS_i,并记录集合大小CiC_i。然后将CC数组从大到小排序,枚举两个运营商i,ji,j,显然,当n≤Ci+Cjn\le C_i + C_j 时i,ji,j才可能满足条件,所以我们做到一个Ci+Cj<nC_i +C_j < n时就可breakbreak。考虑到kk只是nn的十倍,这会是个非常高效的剪枝。
需要注意的是最好少使用bitsetbitset的函数。
代码
#include <cstdio> #include <algorithm> #include <cstring> #include <bitset> using namespace std; const int N = 1e4 + 10; int g ,next[N * 10],to[N * 10],d[N * 10]; int n,m,c ,a ,tot; bitset<N> s ,cur,full; void add(int x,int y,int z) { to[++ tot] = y; next[tot] = g[x]; g[x] = tot; d[tot] = z; } bool cmp(int a,int b) { return c[a] > c[b]; } bool check(int lim) { for (int i = 1;i <= n;i ++) s[i].reset(); for (int u = 1;u <= n;u ++) { c[u] = 0; a[u] = u; for (int i = g[u];i;i = next[i]) if (d[i] <= lim) { int v = to[i]; if (s[u][v]) continue; s[u][v] = 1; c[u] ++; } } sort(a + 1,a + 1 + n,cmp); for (int i = 1;i < n;i ++) { for (int j = i + 1;j <= n;j ++) if (c[a[i]] + c[a[j]] < n) break; else { cur = s[a[i]] | s[a[j]]; if (cur == full) return true; } } return false; } int main() { scanf("%d%d",&n,&m); for (int i = 1;i <= m;i ++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z); } for (int i = 1;i <= n;i ++) full[i] = 1; int ans = 1,r = 1e9; while (ans < r) { int mid = (ans + r) >> 1; if (check(mid)) r = mid; else ans = mid + 1; } if (check(ans)) printf("%d",ans); else printf("No solution"); }
相关文章推荐
- JDBC连接Oracle RAC
- HDOJ 1203 I NEED A OFFER!(01背包)
- MMU初始化
- HttpClient 4.3教程
- 利用Struts进行图片上传
- STL map和unordered_map的区别
- 黑马程序员——OC的Category和Protocol
- 动态规划之背包问题详解
- cocos2dx 玩转音乐播放
- Android-有序广播简单例子
- 【codevs天梯&青铜Bronze】解题报告
- java 字符串json
- 8.26学习总结
- 自定义ExpandableListView
- C语言实现ls命令
- 第K极值
- Android 扫描wifi局域网ip
- 计算子串在主串中的位置及其优化(KMP算法)
- Oracle RAC 客户端连接负载均衡(Load Balance)
- Alice and Bob(贪心HDU 4268)