• hdu 6109 数据分割


    大意:

    输入L组a,b,e,e=1表示a和b在一个集合里面,0表示不在一个集合里面。

    让我们做数据的分组,而成为一组数据的条件是:前i-1组数据都是互不矛盾的,而第i组数据与前i-1组数据的意思有了矛盾。

    输出就是一共能把数据划分为几组,每组有多少个输入数据。

    总体思路是并查集加上一个set维护不相等的集合,set[x]中的所有元素代表和x不相等的点y的集合。

    假设现在处理(a,b,e),思路如下:

    1.首先求得a和b在并查集中的根节点x和y。

    2.如果e等于1,表示a和b在一个集合里:

          若x和y相等,即a和b在一个集合里,我们直接跳过处理。

          若G[x]中包含了y,说明之前出现过(a,b,0)或者(b,a,0),那么我们做一次划分。

          若G[x]中无y,那么合并两个并查集集合x和y,除了修改x指向y,我们还要维护set集合,即把原来和x不在一个集合里边的G[i]里边的x修改成y。

    3.如果e等于0,表示a和b不在一个集合里:

          若x和y相等,说明有矛盾,直接划分一次。

          否则直接维护一下G[x]和G[y],分别插入y和x,以表示两个集合是不等的。

    代码如下所示:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. typedef long long ll;
    9. const ll N=1e5+10;
    10. int L;
    11. int fa[N],a[N],b[N],e[N];
    12. set<int> G[N];
    13. vector<int> ans;
    14. int find_s(int x){
    15. return x == fa[x] ? x : fa[x] = find_s(fa[x]);
    16. }
    17. void init(){
    18. for (int i = 0; i < L; ++i) {
    19. fa[i]=i;
    20. G[i].clear();
    21. }
    22. }
    23. void solve(){
    24. int cnt=0;
    25. for (int i = 0; i < L; ++i) {
    26. cnt++;
    27. int x = find_s(a[i]);
    28. int y = find_s(b[i]);
    29. if (e[i]){
    30. if (x==y) continue;
    31. else if (G[x].find(y)!=G[x].end()){
    32. ans.push_back(cnt);
    33. cnt=0;
    34. init();
    35. }else{
    36. set<int>::iterator it;
    37. for (it = G[x].begin(); it != G[x].end(); ++it) {
    38. G[y].insert(*it);
    39. G[*it].erase(x);
    40. G[*it].insert(y);
    41. }
    42. G[x].clear();
    43. fa[x]=y;
    44. }
    45. }else{
    46. if (x==y){
    47. ans.push_back(cnt);
    48. cnt=0;
    49. init();
    50. }else{
    51. G[x].insert(y);
    52. G[y].insert(x);
    53. }
    54. }
    55. }
    56. }
    57. int main()
    58. {
    59. scanf("%d",&L);
    60. // cout<
    61. for (int i = 0; i < L; ++i) {
    62. scanf("%d %d %d",&a[i],&b[i],&e[i]);
    63. // cout<
    64. }
    65. init();
    66. solve();
    67. int sz=ans.size();
    68. printf("%d\n",sz);
    69. for (int i = 0; i < sz; ++i) {
    70. printf("%d\n",ans[i]);
    71. }
    72. return 0;
    73. }

  • 相关阅读:
    代码技巧——Apache集合类&字符串工具包中实用的API
    CleanMyMac X4.11.2免费版专业的Mac电脑清理软件
    React小记(一)_基础部分
    「专题速递」JPEG AI、端到端图像编码的标准化及产品落地、深度学习
    嗨!不来看一下如何骚气十足的登陆MySQL嘛?
    Vue 搜索历史管理-本地持久化管理
    【MySQL】库和表的操作
    Webrtc源码编译之个人仓库
    C语言 力扣习题 10.19日 day1
    Kotlin 开发Android app(一):Kotlin 建立Android工程
  • 原文地址:https://blog.csdn.net/weixin_46266058/article/details/127734527