bzoj 3624 免费道路

第一遍只加水泥路跑kruscal,找出必须修成石子路的。第二遍kruscal把这些修石子路的修好,然后随便修剩下的路,注意随时判断无解的情况

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>

#define md
#define ll long long
#define inf (int) 1e9
#define eps 1e-8
#define N 20010
#define M 100010
using namespace std;
struct yts{ int x,y;} e[2][M],q[M],ans[M];
int w[2];
int fa[N];
int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]);}
int main()
{
 int n,m,K;
 scanf("%d%d%d",&n,&m,&K);
 for (int i=1;i<=n;i++) fa[i]=i;
 w[0]=w[1]=0;
 for (int i=1;i<=m;i++)
 {
  int x,y,ty;
  scanf("%d%d%d",&x,&y,&ty);
  e[ty][++w[ty]]=(yts){x,y};
 }
 int tot=0;
 for (int i=1;i<=w[1];i++)
 {
  int x=e[1][i].x,y=e[1][i].y;
  int f1=find(x),f2=find(y);
  if (f1!=f2)
  {
   tot++;
   fa[f1]=f2;
  }
 }
 int r=0;
 for (int i=1;i<=w[0];i++)
 {
  int x=e[0][i].x,y=e[0][i].y;
  int f1=find(x),f2=find(y);
  if (f1!=f2)
  {
   tot++; fa[f1]=f2;
   q[++r]=e[0][i];
  }
 }
 if (tot!=n-1) { printf("no solution\n"); return 0;}
 for (int i=1;i<=n;i++) fa[i]=i;
 tot=0;
 for (int i=1;i<=r;i++)
 {
  int x=q[i].x,y=q[i].y;
  int f1=find(x),f2=find(y);
  if (f1!=f2)
  {
   fa[f1]=f2;
   ans[++tot]=q[i];
  }
  if (tot>K) { printf("no solution\n"); return 0;}
 }
 for (int i=1;i<=w[0]&&tot<K;i++)
 {
  int x=e[0][i].x,y=e[0][i].y;
  int f1=find(x),f2=find(y);
  if (f1!=f2)
  {
   fa[f1]=f2;
   ans[++tot]=e[0][i];
  }
 }
 if (tot<K) { printf("no solution\n"); return 0;}
 for (int i=1;i<=w[1]&&tot<n-1;i++)
 {
  int x=e[1][i].x,y=e[1][i].y;
  int f1=find(x),f2=find(y);
  if (f1!=f2)
  {
   fa[f1]=f2;
   ans[++tot]=e[1][i];
  }
 }
 if (tot!=n-1) { printf("no solution\n"); return 0;}
 for (int i=1;i<=K;i++) printf("%d %d 0\n",ans[i].x,ans[i].y);
 for (int i=K+1;i<=tot;i++) printf("%d %d 1\n",ans[i].x,ans[i].y);
 return 0;
}


你可能感兴趣的:(bzoj 3624 免费道路)