UVA 12587 Reduce the Maintenance Cost 解题报告
来源:互联网 发布:2016网络大电影排行 编辑:程序博客网 时间:2024/06/16 01:49
比赛总结
题目
题意:
一个有n个城市m条道路的图,如果一条边删除后,有些城市变得不可达,则它需要维护,花费为L×D,L是道路长度,D是变得不可达的城市对数。每条道路维护花费由连接的城市中的一个承担。城市本来也有固定的维护花费。求所有可能中,花费最大的城市的最小花费。
题解:
首先可以用tarjan求桥,如果(u,v)之间为桥,且u为父亲,则回溯时已遍历的点数-dfn[v]+1就得到和v在同一双连通分量的城市数。
然后由于桥的性质,将所有非桥边删去后图就变成了森林。对于每一棵树可以单独求最小的最大可能花费:
二分答案,然后遍历树,对于当前点而言,如果任意儿子的子树不能将边全部维护,则这答案不可行;
其次,每条连向儿子的边尽可能让儿子维护,否则父亲维护,如果当前点不能维护所有的这样的边,答案不可行;
看看当前点是否能再维护到父亲的边。
//Time:552ms//Length:2742B#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define MAXN 40010#define MOD 1000000007int he[MAXN],to[MAXN],nex[MAXN],len[MAXN],pri[MAXN],top;int dfn[MAXN],low[MAXN],num,sta[MAXN],stop,cnt[MAXN];bool is[MAXN],vi[MAXN],cou[MAXN][2];void add(int u,int v,int w){ to[top]=v; len[top]=w; nex[top]=he[u]; he[u]=top++;}void tarjan(int u,int pre){ dfn[u] = low[u] = num++; sta[stop++]=u; for(int i = he[u]; i != -1; i = nex[i]) { int v = to[i]; if(v==pre) continue; if(dfn[v]==-1) { tarjan(v,u); if(low[v]>dfn[u]) { is[i^1] = is[i]=1; cnt[i^1]=cnt[i]=num-dfn[v]; } low[u]=min(low[u],low[v]); } else low[u] = min(low[u],dfn[v]); }}bool dfs(int h,long long l,long long lim){ long long sum=pri[h]; cou[h][0]=cou[h][1]=0; vi[h]=1; for(int i=he[h];i!=-1;i=nex[i]) if(is[i]&&!vi[to[i]]) { long long tmp=(long long)len[i]*cnt[i]*(stop-cnt[i]); if(!dfs(to[i],tmp,lim)) return false; if(!cou[to[i]][0]) return false; if(!cou[to[i]][1]) sum+=tmp; } if(sum<=lim) cou[h][0]=1; else return false; if(sum+l<=lim) cou[h][1]=1; return true;}bool check(long long lim){ for(int i=0;i<stop;++i) vi[sta[i]]=0; for(int i=0;i<stop;++i) if(!vi[sta[i]]) if(!dfs(sta[i],0,lim)) return false; return true;}int main(){ //freopen("/home/moor/Code/input","r",stdin); int cas,n,m; long long ans,l,r,mid; scanf("%d",&cas); for(int hh=1;hh<=cas;++hh) { scanf("%d%d",&n,&m); l=0; for(int i=1;i<=n;++i) scanf("%d",&pri[i]),l=max(l,(long long)pri[i]); memset(he,-1,sizeof(he)); memset(dfn,-1,sizeof(dfn)); memset(is,0,sizeof(is)); memset(vi,0,sizeof(vi)); memset(cou,0,sizeof(cou)); top=0; for(int i=0;i<m;++i) { int a,b,c; scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } ans=l; for(int i=1;i<=n;++i) if(dfn[i]==-1) { num=0; stop=0; tarjan(i,-1); l=ans; r=1e15; while(l<r) { mid=(l+r)/2; if(check(mid)) r=mid; else l=mid+1; } ans=max(ans,l); } printf("Case %d: ",hh); cout<<ans<<'\n'; } return 0;}
- UVA 12587 Reduce the Maintenance Cost 解题报告
- UVA 12587 Reduce the Maintenance Cost
- UVa 12587 Reduce the Maintenance Cost(Tarjan + 二分 + DFS)
- Uva 12587 Reduce the Maintenance Cost 边双连通+树形dp+贪心
- uvalive 6206 Reduce the Maintenance Cost
- 文章标题 UVALive 6062:Reduce the Maintenance Cost(双联通分量缩点)
- UVa 10878 - Decode the tape 解题报告
- UVa 10785 - The Mad Numerologist解题报告
- UVa 101 - The Blocks Problem解题报告
- UVa 133The Dole Queue解题报告
- UVa 699The Falling Leaves解题报告
- UVa 10562 - Undraw the Trees解题报告
- uva 101 The Blocks Problem 解题报告
- uva 12096 The SetStack Computer 解题报告
- 解题报告(一):uva 10313 - Pay the Price (dp)
- UVA 729 - The Hamming Distance Problem 解题报告
- UVA 539 - The Settlers of Catan 解题报告
- UVa 10474 - Where is the Marble?解题报告
- C++ 虚函数表解析
- IOS动画Core Animation详解
- ANT
- Linux上程序调试的基石(1)--ptrace
- mysql
- UVA 12587 Reduce the Maintenance Cost 解题报告
- 如何实现WebSphere Application Server 6集群环境下的定时服务
- 进程间通信—Socket编程
- Oracle Managed Files(OMF)
- 创建表空间
- C#运算符
- Ubuntu下搭建WebDAV服务器
- GitHub 上删除文件
- 二叉树的前序中序线索化及对对应线索二叉树的遍历