bzoj 3624: [Apio2008]免费道路(并查集+生成树+乱搞)

来源:互联网 发布:重叠覆盖优化案例 编辑:程序博客网 时间:2024/06/06 11:39

3624: [Apio2008]免费道路

Time Limit: 2 Sec  Memory Limit: 128 MBSec  Special Judge
Submit: 727  Solved: 300
[Submit][Status][Discuss]

Description

Input

Output

Sample Input

5 7 2
1 3 0
4 5 1
3 2 0
5 3 1
4 3 0
1 2 1
4 2 1

Sample Output

3 2 0
4 3 0
5 3 1
1 2 1

HINT

Source

[Submit][Status][Discuss]
题解:生成树+并查集+乱搞。

这道题就是求一颗生成树,使特殊边的条数恰好为k 。

那么我们可以把所有非特殊边先加进去,用并查集把所有联通块并在一起,然后开始加特殊边,看是否存在必须加的特殊边(即不加这条边之前这两个点不连通)。

然后我们重新构建生成树,先把所以的必须加的特殊边加进去,然后在加特殊边直到K条,最后再加非特殊边,保证是颗树即可。

注意各种无解的情况,小心处理即可。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define N 20003#define M 100003using namespace std;int n,m,k;int u[M],v[M],c[M];int cnt,x[M],y[M],fa[N],vis[M],belong[M],x1[M],yy[M],c1[M];int find(int x){if (fa[x]==x)  return x;fa[x]=find(fa[x]);return fa[x];}int main(){scanf("%d%d%d",&n,&m,&k);for (int i=1;i<=m;i++) scanf("%d%d%d",&u[i],&v[i],&c[i]);for (int i=1;i<=n;i++) fa[i]=i;for (int i=1;i<=m;i++) if (c[i]&&find(u[i])!=find(v[i]))  {  int r1=find(u[i]); int r2=find(v[i]);  fa[r2]=r1;  }for (int i=1;i<=m;i++) if (!c[i]&&find(u[i])!=find(v[i]))  {  cnt++; vis[m]=1;x[cnt]=u[i]; y[cnt]=v[i]; belong[cnt]=c[i];int r1=find(u[i]); int r2=find(v[i]);  fa[r2]=r1;   }int t=find(1);for (int i=2;i<=n;i++) if (find(i)!=t) { printf("no solution\n"); return 0; }for (int i=1;i<=n;i++)  fa[i]=i;if (cnt>k) {printf("no solution\n");return 0;}int num=0; int tot=0;for (int i=1;i<=cnt;i++) { int r1=find(x[i]); int r2=find(y[i]);  fa[r2]=r1;  num++; tot++;  x1[tot]=x[i]; yy[tot]=y[i]; c1[tot]=belong[i]; }for (int i=1;i<=m;i++) if (!c[i]&&find(u[i])!=find(v[i]))  {  int r1=find(u[i]); int r2=find(v[i]);  fa[r2]=r1; num++; tot++;  x1[tot]=u[i]; yy[tot]=v[i]; c1[tot]=c[i];  if (tot==k)  break;  }if (tot!=k) {printf("no solution\n");return 0;}for (int i=1;i<=tot;i++) printf("%d %d %d\n",x1[i],yy[i],c1[i]);for (int i=1;i<=m;i++) if (c[i]&&find(u[i])!=find(v[i])) { printf("%d %d %d\n",u[i],v[i],c[i]); int r1=find(u[i]); int r2=find(v[i]);  fa[r2]=r1; num++;   if (num==n-1)  break; }}



0 0