[BZOJ3624][Apio2008]免费道路(贪心+并查集)
2017-01-06 09:24
405 查看
题目描述
传送门题解
贪心的思想:首先这一定是一棵生成树,那么我们先做生成树,尽量加水泥路,那么做完之后已经加入的鹅卵石路一定是必须要加的。那么我们打破第一次的生成树,再做一次生成树,首先把必须加的鹅卵石路都加进去,如果鹅卵石路不够k条的话再加进一些凑够k条,之后加水泥路使之成为一颗生成树。也可以值么理解:如果把所有的水泥路都加入到生成树中的话会形成很多连通块,如果想让它成为强连通图的话各个连通块之间必须用水泥路来连接,那么这些水泥路就成了必须加的水泥路。注意生成树的性质:在生成树中任加一条原图边会形成一个环,在这个环中任拆一条边又会变成一个合法的生成树。那么就相当于在原生成树中拆掉了一些水泥路又加上了一些鹅卵石路使之恰好为k条。
那么无解的情况也会判断了吧?
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> using namespace std; const int max_n=2e4+5; const int max_m=1e5+5; int n,m,k,sum[2],f[max_n]; struct hp{int u,v,ty;bool pd;}a[max_m]; inline int cmp(hp a,hp b){return a.ty>b.ty;} inline int cmp1(hp a,hp b){return a.pd<b.pd||a.pd==b.pd&&a.ty<b.ty;} inline int find(int x){ if (x==f[x]) return x; f[x]=find(f[x]); return f[x]; } inline void merge(int x,int y){ int f1=find(x),f2=find(y); f[f1]=f2; } int main(){ scanf("%d%d%d",&n,&m,&k); for (int i=1;i<=m;++i) scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].ty); sort(a+1,a+m+1,cmp); for (int i=1;i<=n;++i) f[i]=i; for (int i=1;i<=m;++i) if (find(a[i].u)!=find(a[i].v)){ merge(a[i].u,a[i].v),a[i].pd=true,sum[a[i].ty]++; if (sum[0]+sum[1]==n-1) break; } if (sum[0]+sum[1]!=n-1||sum[0]>k){printf("no solution\n");return 0;} if (sum[0]==k){ for (int i=1;i<=m;++i) if (a[i].pd) printf("%d %d %d\n",a[i].u,a[i].v,a[i].ty); return 0; } sum[1]=0; for (int i=1;i<=n;++i) f[i]=i; for (int i=1;i<=m;++i) if (a[i].pd&&a[i].ty==0) merge(a[i].u,a[i].v); else a[i].pd=false; sort(a+1,a+m+1,cmp1); for (int i=1;i<=m;++i) if (find(a[i].u)!=find(a[i].v)&&!a[i].pd&&!a[i].ty){ merge(a[i].u,a[i].v); a[i].pd=true; sum[0]++; if (sum[0]==k) break; } if (sum[0]<k){printf("no solution\n");return 0;} for (int i=1;i<=m;++i) if (find(a[i].u)!=find(a[i].v)&&!a[i].pd&&a[i].ty){ merge(a[i].u,a[i].v); a[i].pd=true; sum[1]++; if (sum[1]+sum[0]==n-1) break; } if (sum[0]+sum[1]!=n-1){printf("no solution\n");return 0;} for (int i=1;i<=m;++i) if (a[i].pd) printf("%d %d %d\n",a[i].u,a[i].v,a[i].ty); }
总结
贪心的思路要大胆想。注意生成树的性质。
相关文章推荐
- BZOJ 3624: [Apio2008]免费道路(贪心+并查集)
- 【bzoj3624】[Apio2008]免费道路 贪心+并查集
- 【BZOJ3624】【APIO2008】免费道路(贪心+并查集)
- 【BZOJ3624】【APIO2008】免费道路 [生成树][贪心]
- bzoj 3624: [Apio2008]免费道路【生成树+贪心】
- BZOJ 3624: [Apio2008]免费道路 [生成树 并查集]
- 【并查集】【生成树】【APIO 2008】【bzoj 3624】免费道路
- 【Kruskal+贪心思想】BZOJ3624-[Apio2008]免费道路
- [BZOJ3624][Apio2008]免费道路(并查集)
- bzoj 3624: [Apio2008]免费道路 生成树的构造
- 【bzoj3624】Apio2008—免费道路
- Kruskal算法及其类似原理的应用——【BZOJ 3654】tree&&【BZOJ 3624】[Apio2008]免费道路
- bzoj 3624: [Apio2008]免费道路(并查集+生成树+乱搞)
- bzoj3624 [Apio2008]免费道路
- BZOJ3624 [Apio2008]免费道路
- BZOJ 3624: [Apio2008]免费道路
- BZOJ3624 [Apio2008]免费道路
- 【bzoj3624】【apio2008】免费道路
- [BZOJ]3624: [Apio2008]免费道路 最小生成树
- 【bzoj 3624】: [Apio2008]免费道路