Codeforces 506D Mr. Kitayuta's Colorful Graph 并查集+水水的分类讨论+水水的离线预处理

首先读入所有的边与询问。将边按颜色分类。

按颜色进行并查集,

若此并查集内的点<= 100,则100*100/2的枚举是否联通。

若此并查集内的点  > 100,则将与这些点相关的所有询问查一遍。

那么时间复杂度为100*100/2*(M/100),或者为M/100*Q。

极限的时候两种方法都在一亿左右了,而且每次还需要在map里搞一搞,还要查询是否联通,不知道为啥没有超时。。

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>

#pragma comment(linker, "/STACK:1024000000")
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 6000007

//** I/O Accelerator Interface .. **/
#define g (c=getchar())
#define d isdigit(g)
#define p x=x*10+c-'0'
#define n x=x*10+'0'-c
#define pp l/=10,p
#define nn l/=10,n
template<class T> inline T& RD(T &x)
{
    char c;
    while(!d);
    x=c-'0';
    while(d)p;
    return x;
}
template<class T> inline T& RDD(T &x)
{
    char c;
    while(g,c!='-'&&!isdigit(c));
    if (c=='-')
    {
        x='0'-g;
        while(d)n;
    }
    else
    {
        x=c-'0';
        while(d)p;
    }
    return x;
}
inline double& RF(double &x)      //scanf("%lf", &x);
{
    char c;
    while(g,c!='-'&&c!='.'&&!isdigit(c));
    if(c=='-')if(g=='.')
        {
            x=0;
            double l=1;
            while(d)nn;
            x*=l;
        }
        else
        {
            x='0'-c;
            while(d)n;
            if(c=='.')
            {
                double l=1;
                while(d)nn;
                x*=l;
            }
        }
    else if(c=='.')
    {
        x=0;
        double l=1;
        while(d)pp;
        x*=l;
    }
    else
    {
        x=c-'0';
        while(d)p;
        if(c=='.')
        {
            double l=1;
            while(d)pp;
            x*=l;
        }
    }
    return x;
}
#undef nn
#undef pp
#undef n
#undef p
#undef d
#undef g

using namespace std;

struct Qu
{
    int u,v;
} query[100010];

struct N
{
    int u,v,c;
} edge[100010];

bool cmp(N n1,N n2)
{
    return n1.c < n2.c;
}

int fa[101000];

bool mark[101000];

map<pair<int,int>,int> M;

vector<int> vec[101000],qu;

int Find(int x)
{
    int f = x,t;

    while(f != fa[f])
        f = fa[f];
    while(x != fa[x])
        t = fa[x],fa[x] = f,x = t;
    return f;
}

void Merge(int u,int v)
{
    int fu = Find(u);
    int fv = Find(v);

    if(fu != fv)
    {
        fa[fu] = fv;
    }
}

inline void Cal()
{
    int i,j,k,f,v;
    if(qu.size() > 100)
    {
        for(j = qu.size()-1; j >= 0; --j)
        {
            f = qu[j];
            for(k = vec[f].size()-1; k >= 0; --k)
            {
                if(Find(f) == Find(vec[f][k]))
                    M[pair<int,int>(f,vec[f][k])]++;
            }
        }
    }
    else
    {
        for(i = qu.size()-1;i >= 0; --i)
        {
            f = qu[i];
            for(j = i-1;j >= 0; --j)
            {
                v = qu[j];

                if(Find(f) == Find(v))
                    M[pair<int,int>(min(f,v),max(f,v))]++;

            }
        }
    }

    for(j = qu.size()-1; j >= 0; --j)
        fa[qu[j]] = qu[j],mark[qu[j]] = false;
    qu.clear();
}

int main()
{
    int i,j,n,m,u,v,f,k,pre;

    scanf("%d %d",&n,&m);

    for(i = 1; i <= m; ++i)
        scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].c);

    int q;

    scanf("%d",&q);

    for(i = 1; i <= q; ++i)
    {
        scanf("%d %d",&u,&v);

        if(u > v)
            swap(u,v);

        query[i].u = u;
        query[i].v = v;

        if(M.find(pair<int,int>(u,v)) == M.end())
        {
            vec[u].push_back(v);
            vec[v].push_back(u);
            M.insert(pair<pair<int,int>,int>(pair<int,int>(u,v),0));
        }
    }

    sort(edge+1,edge+m+1,cmp);

    for(i = 1; i <= n; ++i)
        fa[i] = i;

    memset(mark,false,sizeof(mark));

    map<pair<int,int>,int>::iterator it;

    for(pre = edge[1].c,i = 1; i <= m; ++i)
    {
        if(pre == edge[i].c)
        {
            if(mark[edge[i].u] == false)
                qu.push_back(edge[i].u),mark[edge[i].u] = true;
            if(mark[edge[i].v] == false)
                qu.push_back(edge[i].v),mark[edge[i].v] = true;

            Merge(edge[i].u,edge[i].v);
        }
        else
        {
            pre = edge[i].c;
            --i;
            Cal();
        }
    }

    Cal();

    for(i = 1; i <= q; ++i)
    {
        printf("%d\n",M[pair<int,int>(query[i].u,query[i].v)]);
    }

    return 0;
}

Codeforces 506D Mr. Kitayuta's Colorful Graph 并查集+水水的分类讨论+水水的离线预处理

时间: 2024-10-05 11:28:34

Codeforces 506D Mr. Kitayuta's Colorful Graph 并查集+水水的分类讨论+水水的离线预处理的相关文章

Codeforces 506D Mr. Kitayuta&#39;s Colorful Graph(分块 + 并查集)

题目链接  Mr. Kitayuta's Colorful Graph 把每种颜色分开来考虑. 所有的颜色分为两种:涉及的点的个数 $> \sqrt{n}$    涉及的点的个数 $<= \sqrt{n}$ 对于第一种颜色,并查集缩点之后对每个询问依次处理过来若两点连通则答案加一. 对于第二种颜色,并查集所点之后对该颜色涉及的所有点两两之间判断是否连通, 若连通则另外开一个map记录答案. 最后把两个部分的答案加起来即可. 细节问题  由于每种颜色处理完之后并查集都要重新初始化,对于第一种颜色

CodeForces 505B Mr. Kitayuta&#39;s Colorful Graph

Mr. Kitayuta's Colorful Graph Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Practice CodeForces 505B Description Mr. Kitayuta has just bought an undirected graph consisting of n vertices and m edges. The

codeforces 505B Mr. Kitayuta&#39;s Colorful Graph(水题)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Mr. Kitayuta's Colorful Graph Mr. Kitayuta has just bought an undirected graph consisting of n vertices and m edges. The vertices of the graph are numbered from 1 to n. Each edge, namely edge

Codeforces Round #286 (Div. 1) D. Mr. Kitayuta&#39;s Colorful Graph

D - Mr. Kitayuta's Colorful Graph 思路:我是暴力搞过去没有将答案离线,感觉将答案的离线的方法很巧妙.. 对于一个不大于sqrt(n) 的块,我们n^2暴力枚举, 对于大于sqrt(n)的块,我们暴力枚举答案. 这样就能做到严格sqrt(n) * n #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #defin

Codeforces Round #286 div.1 D 506D D. Mr. Kitayuta&#39;s Colorful Graph【并查集】

题目链接:http://codeforces.com/problemset/problem/506/D 题目大意: 给出n个顶点,m条边,每条边上有一个数字,代表某个颜色.不同数字代表不同的颜色.有很多个询问,每个询问问有多少条纯种颜色的路径使得某两个点联通. 分析: 这个题一看就想用并查集来搞,每种颜色用一个并查集处理.对于输入的每条边,我们只需要将这两个点在这条边的颜色对应的并查集中合并就好了.查询的时候,我们只需要检测这两个点在多少个颜色对应的并查集中是在统一集合中的,那么就有多少条纯种颜

Codeforces Round #286 (Div. 2)B. Mr. Kitayuta&#39;s Colorful Graph(dfs,暴力)

数据规模小,所以就暴力枚举每一种颜色的边就行了. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<map> #include<set> #include<vector> #include<algorithm>

Codeforces Round #286 (Div. 2) B. Mr. Kitayuta&#39;s Colorful Graph +foyd算法的应用

B. Mr. Kitayuta's Colorful Graph time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Mr. Kitayuta has just bought an undirected graph consisting of n vertices and m edges. The vertices of the g

DFS/并查集 Codeforces Round #286 (Div. 2) B - Mr. Kitayuta&#39;s Colorful Graph

题目传送门 1 /* 2 题意:两点之间有不同颜色的线连通,问两点间单一颜色连通的路径有几条 3 DFS:暴力每个颜色,以u走到v为结束标志,累加条数 4 注意:无向图 5 */ 6 #include <cstdio> 7 #include <iostream> 8 #include <algorithm> 9 #include <cstring> 10 #include <string> 11 #include <vector> 1

B. Mr. Kitayuta&#39;s Colorful Graph (CF #286 (Div. 2) 并查集)

B. Mr. Kitayuta's Colorful Graph time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Mr. Kitayuta has just bought an undirected graph consisting of n vertices and m edges. The vertices of the g