• BZOJ 3624 [Apio2008]免费道路:并查集 + 生成树 + 贪心【恰有k条特殊路径】


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3624

    题意:

      给你一个无向图,n个点,m条边。

      有两种边,种类分别用0和1表示。

      让你求一棵生成树,使得这棵树中恰好有k条0种类的边。输出每一条边的两端点和种类。

      若无解,则输出"no solution"。

    题解:

      让0和1分别作两种边的边权。

      步骤:

        (1)先找出必须选的0边。(优先选1,最大生成树)

        (2)再将0边个数加至k。

        (3)补上1边。

    AC Code:

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <algorithm>
      5 #include <vector>
      6 #define MAX_N 20005
      7 
      8 using namespace std;
      9 
     10 struct Edge
     11 {
     12     int sour;
     13     int dest;
     14     int len;
     15     Edge(int _sour,int _dest,int _len)
     16     {
     17         sour=_sour;
     18         dest=_dest;
     19         len=_len;
     20     }
     21     Edge(){}
     22     friend bool operator < (const Edge &a,const Edge &b)
     23     {
     24         return a.len<b.len;
     25     }
     26 };
     27 
     28 int n,m,k;
     29 int par[MAX_N];
     30 bool failed=false;
     31 vector<Edge> edge;
     32 vector<Edge> est;
     33 vector<Edge> ans;
     34 
     35 void read()
     36 {
     37     cin>>n>>m>>k;
     38     int a,b,c;
     39     for(int i=0;i<m;i++)
     40     {
     41         cin>>a>>b>>c;
     42         edge.push_back(Edge(a,b,c));
     43     }
     44 }
     45 
     46 void init_union_find()
     47 {
     48     for(int i=1;i<=n;i++)
     49     {
     50         par[i]=i;
     51     }
     52 }
     53 
     54 int find(int x)
     55 {
     56     return par[x]==x?x:par[x]=find(par[x]);
     57 }
     58 
     59 void unite(int x,int y)
     60 {
     61     int px=find(x);
     62     int py=find(y);
     63     if(px==py) return;
     64     par[px]=py;
     65 }
     66 
     67 bool same(int x,int y)
     68 {
     69     return find(x)==find(y);
     70 }
     71 
     72 void max_tree()
     73 {
     74     init_union_find();
     75     sort(edge.begin(),edge.end());
     76     int cnt=0;
     77     for(int i=edge.size()-1;i>=0;i--)
     78     {
     79         Edge temp=edge[i];
     80         if(!same(temp.sour,temp.dest))
     81         {
     82             cnt++;
     83             unite(temp.sour,temp.dest);
     84             if(temp.len==0) est.push_back(temp);
     85         }
     86     }
     87     if(cnt!=n-1 || est.size()>k) failed=true;
     88 }
     89 
     90 void min_tree()
     91 {
     92     init_union_find();
     93     int cnt=0;
     94     int spe=0;
     95     for(int i=0;i<est.size() && spe<k;i++)
     96     {
     97         Edge temp=est[i];
     98         cnt++;
     99         spe++;
    100         ans.push_back(temp);
    101         unite(temp.sour,temp.dest);
    102     }
    103     for(int i=0;i<edge.size();i++)
    104     {
    105         Edge temp=edge[i];
    106         if(!same(temp.sour,temp.dest))
    107         {
    108             if(temp.len==0)
    109             {
    110                 if(spe<k)
    111                 {
    112                     cnt++;
    113                     spe++;
    114                     ans.push_back(temp);
    115                     unite(temp.sour,temp.dest);
    116                 }
    117             }
    118             else
    119             {
    120                 cnt++;
    121                 ans.push_back(temp);
    122                 unite(temp.sour,temp.dest);
    123             }
    124         }
    125     }
    126     if(cnt!=n-1 || spe!=k) failed=true;
    127 }
    128 
    129 void solve()
    130 {
    131     max_tree();
    132     min_tree();
    133 }
    134 
    135 void print()
    136 {
    137     if(failed)
    138     {
    139         cout<<"no solution"<<endl;
    140         return;
    141     }
    142     for(int i=0;i<ans.size();i++)
    143     {
    144         Edge temp=ans[i];
    145         cout<<temp.sour<<" "<<temp.dest<<" "<<temp.len<<endl;
    146     }
    147 }
    148 
    149 int main()
    150 {
    151     read();
    152     solve();
    153     print();
    154 }
  • 相关阅读:
    interview
    lvs简介
    编译参数说明
    nginx-arch
    network
    linux 密码修改方法
    ps命令详解
    sed 命令+正则表达式
    LINUX SCP 命令详解
    linux下mysql的root密码忘记解决方
  • 原文地址:https://www.cnblogs.com/Leohh/p/7636409.html
Copyright © 2020-2023  润新知