题意:你需要花费不超过cost元来搭建一个比赛网络,网络中有n台机器,编号0~n-1,其中机器0为服务器,其他机器为客户机。一共有m条可以使用的网线,其中第i条网线的发送端是机器ui,接收端是机器vi(数据只能从机器ui单向传输到机器vi),带宽是bi Kbps,费用是ci元。每台客户机应当恰好从一台机器接收数据,你的任务是最大化网络中的最小带宽。
思路:二分kbps建立树形图看是否满足条件,提前判断不受kbps最小值为所有边的最小权值条件下是否能够构成树形图,若不行则是impossible,否则二分kbps得出结构
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
typedef long long ll;
const int maxn = 1e4 + 10;
const ll INF = 1e15 + 10;
using namespace std;
struct P {
int u, v, b;
ll c;
P() {}
P(int u, int v, int b, ll c) : u(u), v(v), b(b), c(c) {}
} p[maxn];
int L, R, nn, m, T, t = 1, limit;
int from, to, kb, cost;
ll d[100];
int id[100], par[100], vis[100];
vector<P> g;
bool operator < (P a, P b) {
return a.c < b.c;
}
bool Dmst(int val, int root, int n) {
ll ans = 0;
for(int i = 0; i < m; i++) p[i] = g[i];
while(1) {
fill(d, d + 100, INF); d[root] = 0;
memset(vis, -1, sizeof(vis));
memset(id, -1, sizeof(id));
for(int i = 0; i < m; i++) {
if(p[i].b < val || p[i].u == p[i].v) continue;
if(p[i].v == root || p[i].c >= d[p[i].v]) continue;
d[p[i].v] = p[i].c; par[p[i].v] = p[i].u;
}
for(int i = 0; i < n; i++) {
if(i == root) continue;
if(d[i] == INF) return false;
}
int cnt = 0;
for(int i = 0; i < n; i++) {
ans += d[i];
int v = i;
while(vis[v] != i && id[v] < 0 && v != root) {
vis[v] = i; v = par[v];
}
if(v == root || id[v] >= 0) continue;
for(int u = par[v]; u != v; u = par[u]) id[u] = cnt;
id[v] = cnt++;
}
if(!cnt) break;
for(int i = 0; i < n; i++)
if(id[i] < 0) id[i] = cnt++;
for(int i = 0; i < m; i++) {
int v = p[i].v;
p[i].u = id[p[i].u];
p[i].v = id[p[i].v];
if(p[i].u != p[i].v) p[i].c -= d[v];
}
n = cnt; root = id[root];
}
return ans <= limit;
}
int low(int l, int r) {
while(l < r) {
int mid = l + ((r - l + 1) >> 1);
bool res = Dmst(mid, 0, nn);
if(!res) r = mid - 1;
else l = mid;
}
return l;
}
int main() {
scanf("%d", &T);
while(T--) {
g.clear();
scanf("%d %d %d", &nn, &m, &limit);
L = 1e9; R = 0;
for(int i = 0; i < m; i++) {
scanf("%d %d %d %d", &from, &to, &kb, &cost);
g.push_back(P(from, to, kb, (ll)cost));
R = max(R, kb); L = min(L, kb);
}
sort(g.begin(), g.end());
bool can = Dmst(L, 0, nn);
printf("Case %d: ", t++);
if(!can) { printf("impossible\n"); continue; }
int ans = low(L, R);
printf("%d kbps\n", ans);
}
return 0;
}