题意:有n个点,m条边,每条边有不满意度w[i],以及减小一个不满意度代价c[i],问给你s元用来减少代价,找到一个总不满意度最小的生成树,保证有解。(减少后的不满意度可以为负数)
思路:
显然所有的钱都应该用在生成树中c最小的那条边上
先求出以w[i]为权的最小生成树O(nlogn)
答案一定是在现在求出的最小生成树基础上换掉一条边 或 不变
把所有边进行替换尝试,找到换掉后的最优解。(可以只尝试c不大于mst中最小的c的边)
添加一条边后需要尝试换掉,与该边组成环后的最大权的边,
找最大权就是找新增边的两个节点到最近公共祖先的路径上的最大边

具体见代码

const int maxn =  *  + ;

struct Edge {
int id, u, v, w, c;//从u到v权为w
bool operator < (const Edge& rhs) const {
if (w != rhs.w) return w < rhs.w;
return id < rhs.id;
}
};
vector<Edge> e;
int n, m; int pa[maxn];
vector<pair<int, bool> > G[maxn];
bool vis[maxn]; //被选中的边
int find(int x) {
return pa[x] != x ? pa[x] = find(pa[x]) : x;
}
int kruskal() {
int min_c = INF;
for (int i = ; i <= n; i++) pa[i] = i;
sort(e.begin(), e.end());
for (int i = ; i < e.size(); i++) {
int x = find(e[i].u), y = find(e[i].v);
if (x != y) {
vis[e[i].id] = true;
min_c = min(min_c, e[i].c);
G[e[i].u].push_back(mp(i, ));
G[e[i].v].push_back(mp(i, ));
pa[x] = y;
}
}
return min_c;
} const int maxlog = ; int fa[maxn]; // 父亲数组
int cost[maxn]; // 和父亲的费用
int L[maxn]; // 层次(根节点层次为0)
struct LCA {
int anc[maxn][maxlog]; // anc[p][i]是结点p的第2^i级父亲。anc[i][0] = fa[i]
int maxcost[maxn][maxlog]; // maxcost[p][i]是i和anc[p][i]的路径上的最大费用
// 预处理,根据fa和cost数组求出anc和maxcost数组
void preprocess() {
for(int i = ; i <= n; i++) {
anc[i][] = fa[i]; maxcost[i][] = cost[i];
for(int j = ; ( << j) <= n; j++) anc[i][j] = -;
}
for(int j = ; ( << j) <= n; j++) {
for(int i = ; i <= n; i++) {
if(anc[i][j-] != -) {
int a = anc[i][j-];
anc[i][j] = anc[a][j-];
maxcost[i][j] = max(maxcost[i][j-], maxcost[a][j-]);
}
}
}
}
// 求p到q的路径上的最大权
pii query(int p, int q) {
int tmp, power, i;
if(L[p] < L[q]) swap(p, q); //L[p] >= L[q]
for(power = ; ( << power) <= L[p]; power++);
power--; //(2^power <= L[p]中的最大的)
int ans = -INF;
for(int i = power; i >= ; i--) {
if (L[p] - ( << i) >= L[q]) {
ans = max(ans, maxcost[p][i]);
p = anc[p][i];
}
}
if (p == q) return mp(ans, p); // LCA为p
for(int i = power; i >= ; i--) {
if(anc[p][i] != - && anc[p][i] != anc[q][i]) {
ans = max(ans, maxcost[p][i]); p = anc[p][i];
ans = max(ans, maxcost[q][i]); q = anc[q][i];
}
}
ans = max(ans, cost[p]);
ans = max(ans, cost[q]);
return mp(ans, fa[p]); // LCA为fa[p](它也等于fa[q])
}
} lca; int w[maxn], c[maxn];
int all; void init()
{
scanf("%d%d", &n, &m);
for (int i = ; i < m; i++)
{
scanf("%lld", w + i);
}
for (int i = ; i < m; i++)
{
scanf("%lld", c + i);
}
int u, v;
for (int i = ; i < m; i++)
{
scanf("%d%d", &u, &v);
e.push_back((Edge){i, u, v, w[i], c[i]});
}
scanf("%d", &all);
} void bfs()
{
queue<int> q;
q.push();
fa[] = ;
L[] = ;
cost[] = ;
while (!q.empty())
{
int u = q.front(); q.pop();
for (auto i : G[u])
{
int v = e[i.x].v;
if (i.y) v = e[i.x].u;
if (fa[u] == v)
{
continue;
} q.push(v);
fa[v] = u;
L[v] = L[u] + ;
cost[v] = e[i.x].w;
}
}
} int find_idx(int u, int v) //找边uv的编号
{
if (u == -) cout << "error!" << endl;
for (int i = ; i < G[u].size(); i++)
{
int to = e[G[u][i].x].v;
if (G[u][i].y) to = e[G[u][i].x].u;
if (to == v) return e[G[u][i].x].id;
}
} Edge find_change(const int min_c, LL& sub)
{
Edge ans = (Edge){-};
for (auto i : e)
{
if (vis[i.id] || i.c > min_c) continue;
LL max_wc = lca.query(i.u, i.v).x;
LL new_sub = all / i.c - i.w + max_wc;
if (new_sub > sub)
{
sub = new_sub;
ans = i;
}
}
return ans;
} int find_delete(const Edge& ans)
{
pii father = lca.query(ans.u, ans.v);
pii del(-, -); //删除 del
for (int i = ans.u; i != father.y; i = fa[i])
{
if (cost[i] == father.x)
{
del = mp(i, fa[i]);
break;
}
}
if (del.x == -)
{
for (int i = ans.v; i != father.y; i = fa[i])
{
if (cost[i] == father.x)
{
del = mp(i, fa[i]);
break;
}
}
}
return find_idx(del.x, del.y);
} void solve()
{
int min_c = kruskal();
/*
cout << "MST:" <<endl;
for (auto i : e)
if (vis[i.id]) cout << i.id +1 << " ";
cout << endl;
*/
bfs();
lca.preprocess();
LL sub = all / min_c;
Edge ans = find_change(min_c, sub);
LL sum = ;
for (auto i : e)
{
if (vis[i.id]) sum += i.w;
}
printf("%lld\n", sum - sub);
if (ans.id == -)
{
bool flag = true;
for (auto i : e)
{
if (vis[i.id])
{
if (flag && i.c == min_c)
{
printf("%d %d\n", i.id + , i.w - all / i.c);
flag = false;
}
else
printf("%d %d\n", i.id + , i.w);
}
}
return;
} int idx = find_delete(ans);
for (auto i : e)
{
if (vis[i.id] && i.id != idx)
{
printf("%d %d\n", i.id + , i.w);
}
}
printf("%d %d\n", ans.id + , ans.w - all/ans.c);
} int main()
{
init();
solve();
return ;
}

Codeforces 733F Drivers Dissatisfaction的更多相关文章

  1. 【codeforces 733F】 Drivers Dissatisfaction

    http://codeforces.com/problemset/problem/733/F (题目链接) 题意 给出一张n个点的无向图,每一条变有两个特征值:${w,c}$:分别表示这条边的权值为$ ...

  2. Codeforces Round #378 (Div. 2) F - Drivers Dissatisfaction

    F - Drivers Dissatisfaction 题目大意:给你n个点,m条边,每个边都有一个权重w,每条边也有一个c表示,消耗c元可以把这条边的权重减1,求最多消耗s元的最小生成树. 思路:因 ...

  3. Drivers Dissatisfaction

    Drivers Dissatisfaction time limit per test 4 seconds memory limit per test 256 megabytes input stan ...

  4. CF733F Drivers Dissatisfaction【链剖】【最小生成树应用】

    F. Drivers Dissatisfaction time limit per test 4 seconds memory limit per test 256 megabytes input s ...

  5. 【codeforces 733F】Drivers Dissatisfaction

    [题目链接]:http://codeforces.com/problemset/problem/733/F [题意] 给你n个点m条边; 让你从中选出n-1条边; 形成一个生成树; (即让n个点都联通 ...

  6. Codeforces Round #378 (Div. 2)F - Drivers Dissatisfaction GNU

    http://codeforces.com/contest/733/problem/F 题意:给你一些城市和一些路,每条路有不满意程度和每减少一点不满意程度的花费,给出最大花费,要求找出花费小于s的最 ...

  7. codeforce 378 div 2 F —— Drivers Dissatisfaction (最小生成树,LCA,倍增)

    官方题解: If you choose any n - 1 roads then price of reducing overall dissatisfaction is equal to min(c ...

  8. Drivers Dissatisfaction 最小生成树+LCA

    题意:给一张n个点m条边的连通图,每条边(ai,bi)有一个权值wi和费用ci, 表示这条边每降低1的权值需要ci的花费.现在一共有S费用可以用来降低某些边的权值 (可以降到负数),求图中的一棵权值和 ...

  9. 【CF733F】Drivers Dissatisfaction(最小瓶颈生成树,倍增)

    题意:给出一个图,每条边有权值和花费c,每次花费c能使的权值-1.给出一个预算,求减完权值后的一个最小生成树. 思路:感谢CC大神 有这样一个结论:最佳方案里必定存在一种,预算全部花费全部分配在一条边 ...

随机推荐

  1. Apache—DBUtils框架

    1.所需要jar包 commons-collections-2.1.1.jarmchange-commons-java-0.2.11.jarmysql-connector-java-5.1.18-bi ...

  2. Maven3简介

    Maven3简介 百度百科 maven官网: http:\/\/maven.apache.org\/ Maven下载安装 Maven 下载:http:\/\/maven.apache.org\/dow ...

  3. CAD打开文件总是弹出要求选择字体怎么办

    CAD打开文件总是弹出要求选择字体怎么办1.在C:\Documents and Settings\下搜索acad.fmp文件,双击用记事本打开acad.fmp文件,在最后添加内容,上面几行本来就有,不 ...

  4. JQuery中的id选择器含有特殊字符时,不能选中dom元素

    1.jquery类库在我们实际项目中用的很多,大家经常需要根据控件的id,获取对应的html元素.但是:当id含有特殊字符的时候,是不能选中的 2.jquery的id选择器只支持,单词.阿拉伯数字.下 ...

  5. es6箭头函数中this

    普通函数: $scope.$on('$stateChangeSuccess',function(){this.list = this.getList();}); 箭头函数: $scope.$on('$ ...

  6. Java环境环境配置

    1. 下载并安装JDK,假如安装在D盘 2. 右键计算机->属性->高级系统设置->环境变量 3. 点击新建系统变量:系统变量名:JAVA_HOME   系统变量值:D:\Progr ...

  7. canvas滤镜6种效果吗

    昨天写了一个canvas滤镜的取反色效果,今天加一点效果,主要思路都是一样的,改变getImageData.data[]的值,并返回 代码如下: <!DOCTYPE html> <h ...

  8. class && struct

    http://blog.csdn.net/yuliu0552/article/details/6717915 struct可以包含成员函数,可以继承,可以实现多态. struct为数据结构,class ...

  9. mybaties 查询 语句正确 但是查不到结果

        控制台输出的语句拿到数据库查询就有数据,但是一直显示不出来  也不报错 后来  百度发现数据库连接不对  因为其中引用了两个数据库 所有写混了   ---------------------- ...

  10. Java使用ZXing生成二维码条形码

    一.下载Zxingjar包 本实例使用的是 zxing3.2.0的版本  下载地址 http://pan.baidu.com/s/1gdH7PzP 说明:本实例使用的3.2.0版本已经使用的java7 ...