删边最小生成树
来源:互联网 发布:程序员教程 第4版 pdf 编辑:程序博客网 时间:2024/05/22 16:53
删边最小生成树
时间限制: 1 Sec 内存限制: 128 MB
题目描述
给定一个n个点m条边的无向图,求删除某条之后的最小生成树。
输入
第一行两个整数n和m。
接下来m行,每行3个整数a、b、c
表示有条边连接编号为a和b的节点。输出
输出m行,每行一个整数。
表示如果第i条删除,最小生成树的大小,如果最小生成树不存在,输出-1。样例输入
5 5
1 2 1
2 3 2
1 4 3
2 4 5
4 5 4样例输出
14
-1
12
10
-1提示
30%的数据,n的范围[1,100],m的范围[1,1000];
50%的数据,n的范围[1,300],m的范围[1,3000];
80%的数据,n的范围[1,5000],m的范围[1,50000];
100%的数据,n的范围[1,50000],m的范围[1,200000],边权范围[1,40000];
暴力枚举
int find(int x){ if(x==par[x])return x; return par[x]=find(par[x]);}void check(int x){ int res=n,sum=0; for(int i=1;i<=n;i++)par[i]=i; for(int i=1;i<=m&&res!=1;i++){ if(i==x)continue; a=s[i].a,c=s[i].c,b=s[i].b; fa=find(a),fb=find(b); if(fa==fb)continue; par[fa]=fb;sum+=c;res--; }ans[s[x].id]=res==1?sum:-1;}void solve(){ sort(s+1,s+1+m,cmp); for(int i=1;i<=m;i++){ if(!mark[s[i].id])ans[s[i].id]=pro_sum; else check(i); }}
思路
对于树而言它是无环的
如果加上一条边nw它就形成了一个环
对于环上的任意的一条边删去其中之一它仍为树
即nw可以代替该环上的任意边
那么对于最小生成树而言删去它的代价即为val[x]-val[nw];
所以删可以更新环上任意一条边的答案
显然加入的边要从小到大同时有答案的边无需更新
首先生成最小生成树
void made(){ sort(E+1,E+1+m,cmp); int res=n,a,b,c,id,fa,fb; for(int i=1;i<=m&&res!=1;i++){ a=E[i].a;b=E[i].b; c=E[i].c;id=E[i].id; fa=find(a);fb=find(b); if(fa==fb)continue; G[a].push_back((P){b,c,id}); G[b].push_back((P){a,c,id}); //生成最小生成树 sum+=c;res--; par[fa]=fb;mark[id]=1; }d[1]=1; dfs(1);}
那么如何遍历环呢?;
先预处理出所以的节点的父节点以及其对应的边的边号和代价
void dfs(int x){ for(int i=0;i<G[x].size();i++){ to=G[x][i].t;c=G[x][i].c;id=G[x][i].id; if(!d[to]){ d[to]=d[x]+1; f[to]=x;dfs(to); td[to]=id;tc[to]=c;//记录该节点对应的边的id和c } }}
从a,b节点来向上更新每一条边到LCA
void update(int a,int b){ if(d[a]>d[b])swap(a,b); while(d[a]<d[b]){ id=td[b];c=tc[b];//从节点获取对应的边的id和c if(!use[id])ans[id]=sum-c+cost,use[id]=1; b=f[b]; }while(a!=b){ //一直遍历到LCA(a,b); id=td[b];c=tc[b]; if(!use[id])ans[id]=sum-c+cost,use[id]=1; b=f[b]; id=td[a];c=tc[a]; if(!use[id])ans[id]=sum-c+cost,use[id]=1; a=f[a]; }}
void solve(){ for(int i=1;i<=m;i++) if(!mark[E[i].id]){ a=E[i].a;b=E[i].b;c=E[i].c; cost=c;update(a,b); }for(int i=1;i<=m;i++){ if(!mark[i])printf("%d\n",sum); else printf("%d\n",ans[i]); }return 0;}
综上;
#include<stdio.h>#include<algorithm>#include<vector>#include<string.h>using namespace std;const int M=50005;struct node{int a,b,c,id;}E[M*4];struct P{int t,c,id;};bool cmp(node x,node y){return x.c<y.c;}vector<P>G[M];int par[M],f[M],n,m,sum,d[M];int td[M],tc[M],cost,ans[4*M];bool mark[4*M],use[4*M];int find(int x){ if(x==par[x])return x; return par[x]=find(par[x]);}void dfs(int x){ int to,c,id; for(int i=0;i<G[x].size();i++){ to=G[x][i].t; c=G[x][i].c; id=G[x][i].id; if(!d[to]){ d[to]=d[x]+1; td[to]=id;tc[to]=c; f[to]=x; dfs(to); } }}void update(int a,int b){ int id,c; if(d[a]>d[b])swap(a,b); while(d[a]<d[b]){ id=td[b];c=tc[b]; if(!use[id])ans[id]=sum-c+cost,use[id]=1; b=f[b]; }while(a!=b){ id=td[b];c=tc[b]; if(!use[id])ans[id]=sum-c+cost,use[id]=1; b=f[b]; id=td[a];c=tc[a]; if(!use[id])ans[id]=sum-c+cost,use[id]=1; a=f[a]; }}void made(){ sort(E+1,E+1+m,cmp); int res=n,a,b,c,id,fa,fb; for(int i=1;i<=m&&res!=1;i++){ a=E[i].a;b=E[i].b; c=E[i].c;id=E[i].id; fa=find(a);fb=find(b); if(fa==fb)continue; G[a].push_back((P){b,c,id}); G[b].push_back((P){a,c,id}); sum+=c;res--; par[fa]=fb;mark[id]=1; }d[1]=1; dfs(1);}int main(){ int a,b,c,id; memset(ans,-1,sizeof(ans)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d%d",&a,&b,&c); E[i]=(node){a,b,c,i}; } for(int i=1;i<=n;i++)par[i]=i; made(); for(int i=1;i<=m;i++) if(!mark[E[i].id]){ a=E[i].a;b=E[i].b;c=E[i].c; cost=c;update(a,b); }for(int i=1;i<=m;i++){ if(!mark[i])printf("%d\n",sum); else printf("%d\n",ans[i]); }return 0;}
3 0
- 删边最小生成树
- LA3887 最小生成树 枚举最小边
- 【最小生成树】CF160D最小生成树中的边
- 最小比例 最小生成树
- 最小生成树&&次最小生成树
- 最小生成生成树计数
- 最小生成树的最大边poj2395
- poj2395(最小生成树最大边)
- hdu4126(最小生成树最佳替换边)
- hdu4756(最小生成树最佳替换边)
- 树+最小生成树
- 最小生成树
- 最小生成树 MST
- 最小生成树Kruskal
- kruskal 最小生成树
- 最小生成树
- 最小生成树
- 最小生成树
- 阅读论文
- 【拼接最小字典序字符串】(python)
- hdu5924
- Markdown编辑器写博客
- FFMPEG MPEG传输流混合器
- 删边最小生成树
- Spring项目的配置
- 生成随机字符串并排序
- 关于pthread_detach
- 07-图4 哈利·波特的考试 (25分)
- POJ 3271 Lilypad Pond 最短路径的转化
- opwenwrt交叉编译(二)——交叉编译环境的搭建(Ubuntu)
- python网页爬虫代理
- C++多文件结构和编译预处理命令