UVa 12587 Reduce the Maintenance Cost(Tarjan + 二分 + DFS)
题意:n个城市(n <= 10000), 有m条边(m <= 40000),每一个城市有一个维护费用Cost(i),除此之外,每条边的维修费用为去掉该边后不能通信的城市对数与边权的积。这个费用要加到这条边的两端城市的某一个,问你全部城市的最大费用的最小值。、
思路:首先边的费用能够通过Tarjan求桥之后求得(利用桥的性质),然后就是二分答案了!对于每一个点,假设有个儿子不能维护。那么不可行,否则。试着让儿子去维护边权,假设不可行,仅仅能让父亲承担。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long LL;
const int maxn = 10000+10;
const int maxm = 40000+10;
LL cost[maxn];
int head[maxn];
int n,m;
int dfn[maxn],lown[maxn];
bool CanE[maxn];
int cnt[maxm];
LL ans;
int nume,dfs_clock;
bool vis[maxn];
bool isBridge[maxm];
vector<int> sta;
struct edge{
int u,v,w,nxt;
}e[maxm]; void Tarjan(int u,int fa) {
lown[u] = dfn[u] = dfs_clock++;
sta.push_back(u);
for(int i = head[u]; i ; i = e[i].nxt) {
int v = e[i].v;
if(v==fa) continue;
if(!dfn[v]) {
Tarjan(v,u);
lown[u] = min(lown[u],lown[v]);
if(lown[v] > dfn[u]) {
isBridge[i] = isBridge[i^1] = true;
cnt[i] = cnt[i^1] = dfs_clock-dfn[v];
}
}else {
lown[u] = min(lown[u],dfn[v]);
}
}
}
bool dfs(int u,LL s,LL x) {
vis[u] = true;
LL ts = cost[u];
int sz = sta.size();
for(int i = head[u]; i; i = e[i].nxt) {
int v = e[i].v, w = e[i].w;
if(isBridge[i] && !vis[v]) {
LL tmp = (LL)w*cnt[i]*(sz-cnt[i]);
if(!dfs(v,tmp,x)) return false;
if(!CanE[v]) ts += tmp;
}
}
if(ts > x) return false;
if(ts+s <= x) CanE[u] = true;
return true;
}
bool can(LL x) {
int len = sta.size();
memset(CanE,false,sizeof CanE);
for(int i = 0; i < len; i++) vis[sta[i]] = false;
for(int i = 0; i < len; i++) {
int t = sta[i];
if(vis[t]) continue;
if(!dfs(t,0,x)) return false;
}
return true;
}
void init() {
nume = 1;
ans = 0;
dfs_clock = 1;
memset(head,0,sizeof head);
memset(isBridge,false,sizeof isBridge);
memset(vis,false,sizeof vis);
memset(dfn,0,sizeof dfn);
memset(lown,0,sizeof lown);
memset(CanE,false,sizeof CanE);
sta.clear();
}
void addedge(int u,int v,int w) {
e[++nume].nxt = head[u];
e[nume].u = u;
e[nume].v = v;
e[nume].w = w;
head[u] = nume;
}
void solve() {
for(int i = 1; i <= n; i++) {
if(!dfn[i]) {
sta.clear();
Tarjan(i,-1);
LL L = ans,R = 1e10;
while(L <= R) {
LL mid = (L+R)/2;
if(can(mid)) {
R = mid-1;
}else{
L = mid+1;
}
}
ans = max(ans,L);
}
}
printf("%lld\n",ans);
}
int main(){ int ncase,T=1;
cin >> ncase;
while(ncase--) {
init();
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) {
scanf("%lld",&cost[i]);
ans = max(ans,cost[i]);
}
for(int i = 0; i < m; i++) {
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);
}
printf("Case %d: ",T++);
solve();
}
return 0;
}
UVa 12587 Reduce the Maintenance Cost(Tarjan + 二分 + DFS)的更多相关文章
- UVA.10474 Where is the Marble ( 排序 二分查找 )
UVA.10474 Where is the Marble ( 排序 二分查找 ) 题意分析 大水题一道.排序好找到第一个目标数字的位置,返回其下标即可.暴力可过,强行写了一发BS,发现错误百出.应了 ...
- Codeforces Round #381 (Div. 2)D. Alyona and a tree(树+二分+dfs)
D. Alyona and a tree Problem Description: Alyona has a tree with n vertices. The root of the tree is ...
- [BZOJ 1082] [SCOI2005] 栅栏 【二分 + DFS验证(有效剪枝)】
题目链接:BZOJ - 1082 题目分析 二分 + DFS验证. 二分到一个 mid ,验证能否选 mid 个根木棍,显然要选最小的 mid 根. 使用 DFS 验证,因为贪心地想一下,要尽量先用提 ...
- 51nod1307(暴力树剖/二分&dfs/并查集)
题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1307 题意: 中文题诶~ 思路: 解法1:暴力树剖 用一个数 ...
- uva 12587 二分枚举
思路:维护一个森林,二分枚举最小的最大值. #include<set> #include<map> #include<cmath> #include<queu ...
- 【UVA 11865】 Stream My Contest (二分+MDST最小树形图)
[题意] 你需要花费不超过cost元来搭建一个比赛网络.网络中有n台机器,编号0~n-1,其中机器0为服务器,其他机器为客户机.一共有m条可以使用的网线,其中第i条网线的发送端是机器ui,接收端是机器 ...
- Codeforces 901C Bipartite Segments(Tarjan + 二分)
题目链接 Bipartite Segments 题意 给出一个无偶环的图,现在有$q$个询问.求区间$[L, R]$中有多少个子区间$[l, r]$ 满足$L <= l <= r &l ...
- UVA 11419 SAM I AM(最大二分匹配&最小点覆盖:König定理)
题意:在方格图上打小怪,每次可以清除一整行或一整列的小怪,问最少的步数是多少,又应该在哪些位置操作(对输出顺序没有要求). 分析:最小覆盖问题 这是一种在方格图上建立的模型:令S集表示“行”,T集表示 ...
- uva 11324 The Largest Clique (Tarjan+记忆化)
/*每个环 要么不选 要么全选 可缩点 就得到一个GAD图 然后搞搞算出最大路径*/ #include<iostream> #include<cstdio> #include& ...
随机推荐
- C语言常见的函数调用
C语言常见的函数调用 isatty,函数名,主要功能是检查设备类型,判断文件描述词是否为终端机. 函数名: isatty 用 法: int isatty(int desc); 返回值:如果参数desc ...
- 九度oj 题目1342:寻找最长合法括号序列II
题目描述: 假如给你一个由’(‘和’)’组成的一个随机的括号序列,当然,这个括号序列肯定不能保证是左右括号匹配的,所以给你的任务便是去掉其中的一些括号,使得剩下的括号序列能够左右括号匹配且长度最长,即 ...
- AWR报告中Parse CPU to Parse Elapsd%的理解
AWR报告中Parse CPU to Parse Elapsd%的理解 原文自:http://dbua.iteye.com/blog/827243 Parse CPU to Parse Ela ...
- POJ 1125 Stockbroker Grapevine【floyd】
很裸的floyd #include<cstdio> #include<string.h> #include<algorithm> #define maxn 201 ...
- 算法复习——无源汇可行流(zoj2314)
题目: The terrorist group leaded by a well known international terrorist Ben Bladen is buliding a nucl ...
- 算法复习——欧拉回路混合图(bzoj2095二分+网络流)
题目: Description YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛.现在YYD想骑单车 ...
- DP的序--Codeforces626F. Group Projects
$n \leq 200$个数,$ \leq 500$,$K \leq 1000$代价内的数字分组有多少?一个分组的代价是分成的每个小组的总代价:一个小组的代价是极差. 问的极差那就从极入手嘛.一个小组 ...
- Kail命令
启动/关闭无线网卡 ifconfig wlan0 up / ifconfig wlan0 down 更改Mac地址: macchanger -A wlan0 启动监听 airmon-ng star ...
- UI小结
第一.UIButton的定义 UIButton *button=[[UIButton buttonWithType:(UIButtonType); 能够定义的button类型有以下6种, ...
- windows安装RabbitMQ注意事项
1.首先下载好ERLANG.RabbitMQ安装包,先安装erlang,设置好环境变量,然后再去安装MQ; 2.别人有两个报错: 一:RabbitMQ安装目录中不允许有空格; 二:安装rabbitmq ...