例题5.22 比赛网络 UVa11865
来源:互联网 发布:php 图片水印 编辑:程序博客网 时间:2024/04/28 07:23
1.题目描述:点击打开链接
2.解题思路:本题利用二分+最小树形图解决。根据题意显然应该用二分法,假设当前带宽为x,那么问题转化为:能否用带宽大于等于x的网线搭建起来网络?根据题意描述可知,这个网络是一个有向带权图,如果可以从根到达所有结点的话,那么其中一定存在最小树形图,我们可以用朱刘算法求解出这个最小树形图的权值之和,即最终需要的费用,如果这个费用小于等于给定的cost,那么说明有解,否则无解(因为最小树形图的权值之和一定是最小的)。
3.代码:
#include<iostream>#include<algorithm>#include<cassert>#include<string>#include<sstream>#include<set>#include<bitset>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<cctype>#include<list>#include<complex>#include<functional>using namespace std;#define me(s) memset(s,0,sizeof(s))#define rep(i,n) for(int i=0;i<(n);i++)#define pb push_backtypedef long long ll;typedef pair <int,int> P;const int INF=1e9;const int maxn=100+10;struct MDST //求解固定根的最小有向生成树,邻接矩阵写法{ int n; int w[maxn][maxn]; //边权 int vis[maxn]; //访问标记,仅用来判断无解 int ans; //答案 int removed[maxn]; //标记点是否被删除 int cid[maxn]; //所在圈的编号 int pre[maxn]; //最小入边的起点 int iw[maxn]; //最小入边的权值 int max_cid; //最大圈编号 void init(int n) { this->n=n; for(int i=0;i<n;i++) for(int j=0;j<n;j++) w[i][j]=INF; } void addedge(int u,int v,int cost) { w[u][v]=min(w[u][v],cost); //重边取最小的 } int dfs(int s)//计算从s出发可以访问多少个结点 { vis[s]=1; int ans=1; for(int i=0;i<n;i++) if(!vis[i]&&w[s][i]<INF) ans+=dfs(i); return ans; } bool cycle(int u)//从u出发沿着pre指针找圈 { max_cid++; int v=u; while(cid[v]!=max_cid){cid[v]=max_cid;v=pre[v];} return v==u; } void update(int u)//计算u的最小入弧,最小入弧不得在圈中 { iw[u]=INF; for(int i=0;i<n;i++) if(!removed[i]&&w[i][u]<iw[u]) { iw[u]=w[i][u]; pre[u]=i; } } bool solve(int s)//根节点为s,去寻找最小树形图,如果无解返回false { me(vis); if(dfs(s)!=n)return false; //如果不能全部连通,那么无解 memset(removed,0,sizeof(removed)); memset(cid,0,sizeof(cid)); for(int u=0;u<n;u++)update(u); //计算所有顶点的最小入弧 pre[s]=s;iw[s]=0; //根结点特殊处理 ans=max_cid=0; for(;;) { bool have_circle=false; for(int u=0;u<n;u++) if(u!=s&&!removed[u]&&cycle(u)) { have_circle=true; int v=u; do //进行缩圈操作,圈上除了u之外,其他点都删除 { if(v!=u) removed[v]=1; ans+=iw[v]; for(int i=0;i<n;i++) if(cid[i]!=cid[u]&&!removed[i]) { if(w[i][v]<INF)w[i][u]=min(w[i][u],w[i][v]-iw[v]);//对于圈外点i,把i->v改成i->u;v->i改成u->i w[u][i]=min(w[u][i],w[v][i]); if(pre[i]==v)pre[i]=u; } v=pre[v]; }while(v!=u); update(u); break; } if(!have_circle)break; } for(int i=0;i<n;i++) if(!removed[i])ans+=iw[i]; return true; }};MDST solver;struct Edge{ int u,v,b,c; bool operator<(const Edge&rhs)const { return b>rhs.b; }};const int maxm=10000+10;int n,m,C;Edge edges[maxm];bool check(int cnt)//看用前cnt根网线能否成功搭建网络{ solver.init(n); for(int i=0;i<cnt;i++) solver.addedge(edges[i].u,edges[i].v,edges[i].c); if(!solver.solve(0))return false; return solver.ans<=C;}int main(){ int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&C); for(int i=0;i<m;i++) scanf("%d%d%d%d",&edges[i].u,&edges[i].v,&edges[i].b,&edges[i].c); sort(edges,edges+m); int L=1,R=m,ans=-1; while(L<=R) { int mid=L+(R-L)/2; if(check(mid)){ans=edges[mid-1].b;R=mid-1;} else L=mid+1; } if(ans<0)puts("streaming not possible."); else printf("%d kbps\n",ans); }}
0 0
- 例题5.22 比赛网络 UVa11865
- 【UVA11865】比赛网络(二分+有向生成树)
- uva11865
- 例题3.7 乒乓比赛 UVa1428
- 例题10-14 比赛名次 UVa12034
- 网络流例题总结
- 例题15 网络
- 网络流例题
- uva11865 - Stream My Contest
- 最小树形图uva11865
- 第三章 例题7(乒乓比赛)基础树状数组
- 例题11-11 赛车比赛 单源最短路 spfa
- 例题1.15 网络 UVALive 3902
- 例题3.6 合作网络 UVa1329
- 网络流(模版+例题)
- 网络流例题及构图选讲
- LA2957 网络流 蓝书例题
- 网络打字比赛软件 v6.1.3 绿色
- python工作原理
- UI 实现多线程方式之二 NSThread
- 51nod 1242 1242 斐波那契数列的第N项
- Ubuntu vim的使用基础
- 将Vim改造为强大的IDE—Vim集成Ctags/Taglist/Cscope/Winmanager/NERDTree/OmniCppComplete(有图有真相)
- 例题5.22 比赛网络 UVa11865
- UI 实现多线程方式之三 NSOperation+NSOperationQueue
- 数据结构实践——排队看病模拟(队列)
- [面试时]MySQL索引背后的数据结构及算法原理
- iOS编程------- Block高级------>Block传值
- iOS中nil NULL Nil 和NSNull区别
- CATIA入门第一天
- 在windows上部署redis服务,以及使用jedis客户端。
- C++中的虚函数(类的向上转换,和向下转换)