zoukankan      html  css  js  c++  java
  • [loj3462]括号路径

    对于两条边$(x_{1},y,c)$和$(x_{2},y,c)$,不难发现$x_{1}$与$x_{2}$完全等价,因此可以合并

    重复此过程,合并之后用启发式合并来合并边集(注意自环也可以参与合并,即$(x,y,c)$和$(y,y,c)$,那么就将$x$和$y$合并),并用一个队列来记录操作

    之后,当不存在此类边,考虑一条合法路径中必然有相邻两次,选择了同类型的左右括号(先左后右),由于不存在此类边,不难证明这只能在一条边上往返,显然无意义,即只能在合并后的集合内部选,并查集维护即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 300005
     4 struct ji{
     5     int x,c,y;
     6 };
     7 queue<ji>q;
     8 map<int,int>mat[N];
     9 map<int,int>::iterator it;
    10 int n,m,k,x,y,z,f[N],sz[N];
    11 long long ans;
    12 int find(int k){
    13     if (k==f[k])return k;
    14     return f[k]=find(f[k]);
    15 }
    16 void merge(int x,int y){
    17     x=find(x),y=find(y);
    18     if (x==y)return;
    19     if (mat[x].size()<mat[y].size())swap(x,y);
    20     f[y]=x;
    21     sz[x]+=sz[y];
    22     for(it=mat[y].begin();it!=mat[y].end();it++)
    23         q.push(ji{x,(*it).first,(*it).second});
    24 }
    25 int main(){
    26     scanf("%d%d%d",&n,&m,&k);
    27     for(int i=1;i<=n;i++){
    28         f[i]=i;
    29         sz[i]=1;
    30     } 
    31     for(int i=1;i<=m;i++){
    32         scanf("%d%d%d",&x,&y,&z);
    33         q.push(ji{y,z,x});
    34     }
    35     while (!q.empty()){
    36         ji o=q.front();
    37         q.pop();
    38         o.x=find(o.x);
    39         if (!mat[o.x][o.c])mat[o.x][o.c]=o.y;
    40         else merge(mat[o.x][o.c],o.y);
    41     }
    42     for(int i=1;i<=n;i++)
    43         if (f[i]==i)ans+=1LL*sz[i]*(sz[i]-1)/2;
    44     printf("%lld",ans);
    45 }
    View Code
  • 相关阅读:
    EL表达式具体解释
    Android 实战美女拼图游戏 你能坚持到第几关
    redis sentinel安装及配置(单机版)
    ElasticSearch scroll查询 api
    springboot自动配置原理
    kafka实践
    Springboot mybatis
    计算机原理
    快速排序算法
    maven常见报错问题
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14382838.html
Copyright © 2011-2022 走看看