码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-01-21 10:18:34      阅读:302      评论:0      收藏:0      [点我收藏+]

标签:

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

按颜色进行并查集,

若此并查集内的点<= 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 并查集+水水的分类讨论+水水的离线预处理

标签:

原文地址:http://blog.csdn.net/zmx354/article/details/42963761

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!