hihoCoder 1160 攻城略地 编程之美2015初赛第二场
来源:互联网 发布:linux dd windows u盘 编辑:程序博客网 时间:2024/05/01 19:03
这一题一共有两种做法,第一种是用并查集,算出删除每一条边带来的最小代价是多少,然后删除前k条边后,再计算后面n-k条边的代价。第二种是用连通分量+贪心。
根据题意,每一个连通分量只要攻占其代价最小的城市,即可攻占整个连通分量。因为删除道路只会使得连通分量有增无减,显然只删除k条道路最优。
对于一颗树而言,每删除一条边都会增加一个连通分量。为了减少代价,对于原始的图,我们开始会选择删除那些不会增加连通分量的边。n的节点的连通图,其生成树有n-1条边。非连通的图,其生成树们有n-connectedcnt条边,connectedcnt是连通分量的个数。最终的图有m-k条边,所以再删除n-connectedcnt-(m-k)条边时,每删一条都会增加一个连通分量,每个连通分量的代价又可以通过一个节点的代价代替。
先通过dfs求出连通分量的个数,并记录每个连通分量中代价最小的节点。之后忽略这些节点,按照代价从小到大排序并选择前n-connectedcnt-(m-k)个节点即可。PS:我用bfs就一直TLE是什么鬼,难道这又是水过去的算法?
#include<iostream>#include<stdio.h>#include<cstdio>#include<stdlib.h>#include<vector>#include<string>#include<cstring>#include<cmath>#include<algorithm>#include<stack>#include<queue>#include<ctype.h>#include<map>#include<time.h>#include<bitset>#include<set>#include<list>using namespace std;//hiho 1160const int maxn=1000010;const int INF=0x3f3f3f3f;int T;int n;int m;int k;int w[maxn];vector<int>mp[maxn];long long ans;bool vis[maxn];int val;int idx;int connectedcnt;void bfs(int st)//lead to TLE{// val=INF;// idx=0; queue<int>q; //while(!q.empty()) q.pop(); q.push(st); while(!q.empty()) { int tmp=q.front(); vis[tmp]=true; if(val>w[tmp]) { val=w[tmp]; idx=tmp; } q.pop(); for(int i=0;i<mp[tmp].size();i++) { int to=mp[tmp][i]; if(vis[to]==false) { q.push(to); //vis[to]=true; } } }}void dfs(int u){ vis[u]=true;// val=INF;必须在递归外面设初值// idx=0; if(w[u]<val) { val=w[u]; idx=u; } for(int i=0;i<mp[u].size();i++) { int v=mp[u][i]; if(vis[v]==false) { dfs(v); } }}int main(){ freopen("input.txt","r",stdin); scanf("%d",&T); for(int ca=1;ca<=T;ca++) { scanf("%d %d %d",&n,&m,&k); ans=0; connectedcnt=0; memset(w,0,sizeof(w)); //memset(mp,0,sizeof(mp)); memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++) { scanf("%d",&w[i]); mp[i].clear(); } for(int i=0;i<m;i++) { int a=0; int b=0; scanf("%d %d",&a,&b); mp[a].push_back(b); mp[b].push_back(a); } for(int i=1;i<=n;i++) { if(vis[i]==false) { val=INF; //bfs(i); dfs(i); ans+=val; w[idx]=INF; connectedcnt++; } } int remain=n-connectedcnt-m+k; sort(w+1,w+n+1); for(int i=1;i<=remain;i++) { ans+=w[i]; } printf("Case #%d: %lld\n",ca,ans); } return 0;}
0 0
- hihoCoder 1160 攻城略地 编程之美2015初赛第二场
- 编程之美初赛第二场 攻城略地(贪心,图论)
- hihoCoder 1159 扑克牌 编程之美2015初赛第二场
- hihoCoder 1161 八卦的小冰 编程之美2015初赛第二场
- 2015编美第二场攻城略地
- 编程之美-初赛第二场
- 编程之美初赛第二场 集合
- 2014编程之美初赛第二场
- 2014编程之美初赛第二场
- 2014编程之美初赛第二场
- 编程之美初赛第二场 集合
- 编程之美初赛第二场 集合
- 编程之美初赛第二场
- 2015编程之美初赛第二场扑克牌
- 编程之美2015初赛第二场AB
- 编程之美2014初赛第二场第二题
- hihoCoder 1156 彩色的树 编程之美2015初赛第一场
- 2013编程之美全国挑战赛初赛第二场-集会
- 进程,创建,vfork
- 通过wifi离线推广ios app
- 读书笔记11:建造者模式
- 如何成为一名黑客
- 读书笔记12:观察者模式
- hihoCoder 1160 攻城略地 编程之美2015初赛第二场
- 读书笔记13:状态模式
- 读书笔记14:适配器模式
- SpringMVC 流程(5)-- 视图解析器
- 读书笔记15:备忘录模式
- Android内存管理之道
- Cocos2dx之CCLabelBMFont类
- C# Enumerable 类
- 教您在MathType输入三角形符号