题意
n 个运营商,每个运营商可以发送短信给其他的一些运营商。彼得可以选两个运营商,通过两个运营商中花钱更少的一个发送短信给运营商。帮助彼得选择一对运营商,使得他能够发送短信给所有运营商,而且发送短信的最大费用最小。
运营商能发送短信的关系数
k≤105
Time
Limits:2000ms
Memory
Limits:64M
分析
这题其实就是暴力优化。
考虑二分答案。用
bitset
记录一个运营商
i
在当前答案限制下能发给的运营商的集合
需要注意的是最好少使用 bitset 的函数。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <bitset>
using namespace std;
const int N = 1e4 + 10;
int g[N],next[N * 10],to[N * 10],d[N * 10];
int n,m,c[N],a[N],tot;
bitset<N> s[N],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");
}