zoukankan      html  css  js  c++  java
  • 2017北京ICPC C题 Graph

    #1629 : Graph

    时间限制:4000ms
    单点时限:4000ms
    内存限制:256MB

    描述

    The country contains N cities numbered from 1 to N and M undirected roads connecting pairs of cities. There are some queries. Each query is represented by two numbers: L and R , meaning that all the cities whose number is between L and R(L and R are included) are safe, and other cities are not safe. We define city A can reach city B if and only if they are both safe and there exists a path from A to B that the cities on the path are all safe.

    For each query, you need to figure out the number of pairs of cities that can reach each other under the condition given by the query.

    输入

    First line contains one number T which means the number of test cases.

    For each test case, first line contains three numbers, above mentioned N , M and Q.

    Next M lines, each line contains two integers: X, Y (X != Y) which means there is a road between city X and city Y (1 <= X,Y <= N).

    Next Q lines, each line contains two numbers: L, R which indicates an query(1 <= L,R <= N, L <= R).

    T <= 5, N , M <= 50000, Q <= 100000

    输出

    For each test case, output Q lines, each line contains the answer of the correspondent query.

    样例输入
    1
    6 6 4
    1 2
    2 3
    2 6
    1 5
    2 4
    4 5
    1 4
    3 6
    2 6
    3 4
    样例输出
    6
    1
    10
    0
    分析:对于询问(L,R),可行的边(x,y)满足L<=x<=y<=R;
       那么分成两部分,满足L<=x的边与y<=R的边的交即可;
       于是把边拷贝两份分别排序求前缀交,可以离线用回滚莫队转移;
       维护答案用并查集即可;
    代码:
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <bitset>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cassert>
    #include <ctime>
    #define rep(i,m,n) for(i=m;i<=(int)n;i++)
    #define inf 0x3f3f3f3f
    #define mod 19260817
    #define vi vector<int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    #define pii pair<int,int>
    #define sys system("pause")
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    #define all(x) x.begin(),x.end()
    const int maxn=1e5+10;
    const int N=2e5;
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;}
    int n,m,k,t,q,num,bl[maxn],fa[maxn],sz[maxn],cnt[2][maxn],tot,L[maxn],R[maxn];
    ll ret,lst,ans[maxn];
    struct node
    {
        int u,v,id;
        bool operator<(const node&p)const
        {
            return bl[u]==bl[p.u]?v<p.v:bl[u]<bl[p.u];
        }
    }e[maxn],f[maxn],qu[maxn],tmp[maxn];
    bool cmp1(node x,node y)
    {
        return x.u>y.u;
    }
    bool cmp2(node x,node y)
    {
        return x.v<y.v;
    }
    int find(int x){return fa[x]==x?x:find(fa[x]);}
    void unite(int x,int y)
    {
        x=find(x),y=find(y);
        if(x==y)return;
        if(sz[x]>sz[y])swap(x,y);
        fa[x]=y;
        ret+=(ll)sz[y]*sz[x];
        sz[y]+=sz[x];
    }
    void undo()
    {
        while(tot)
        {
            int x=tmp[tot].u,y=tmp[tot].v;
            fa[x]=x;
            sz[y]-=sz[x];
            ret-=(ll)sz[y]*sz[x];
            tot--;
        }
    }
    int main(){
        int i,j;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&m,&q);
            rep(i,1,m)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                if(x>y)swap(x,y);
                e[i]=f[i]=node{x,y,i};
            }
            sort(e+1,e+m+1,cmp1);
            sort(f+1,f+m+1,cmp2);
            int pos=0;
            for(i=n;i>=1;i--)
            {
                while(pos+1<=m&&e[pos+1].u>=i)pos++;
                L[i]=pos;
            }
            pos=0;
            rep(i,1,n)
            {
                while(pos+1<=m&&f[pos+1].v<=i)pos++;
                R[i]=pos;
            }
            num=round(sqrt(m)+0.5);
            rep(i,1,m)bl[i]=(i-1)/num+1;
            rep(i,1,q)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                if(x>y)swap(x,y);
                qu[i]=node{L[x],R[y],i};
            }
            sort(qu+1,qu+q+1);
            int l,r;
            rep(i,1,q)
            {
                if(i==1||bl[qu[i].u]!=bl[qu[i-1].u])
                {
                    rep(j,1,n)fa[j]=j,sz[j]=1;
                    rep(j,1,m)cnt[0][j]=cnt[1][j]=0;
                    ret=tot=0;
                    j=1;
                    while(j<=m&&j<=bl[qu[i-1].u]*num)++cnt[0][e[j++].id];
                    l=j,r=1;
                }
                while(r<=m&&r<=qu[i].v)
                {
                    if(++cnt[1][f[r].id]==1&&cnt[0][f[r].id])
                    {
                        unite(f[r].u,f[r].v);
                    }
                    r++;
                }
                lst=ret;
                while(l<=m&&l<=qu[i].u)
                {
                    if(++cnt[0][e[l].id]==1&&cnt[1][e[l].id])
                    {
                        int x=find(e[l].u),y=find(e[l].v);
                        if(x!=y)
                        {
                            if(sz[x]>sz[y])swap(x,y);
                            tmp[++tot]=node{x,y,0};
                            unite(x,y);
                        }
                    }
                    l++;
                }
                while(l>j)
                {
                    --cnt[0][e[--l].id];
                }
                ans[qu[i].id]=ret;
                undo();
                ret=lst;
            }
            rep(i,1,q)printf("%lld
    ",ans[i]);
        }
        return 0;
    }
    /*
    1
    3 3 6
    1 2
    2 3
    3 1
    1 1
    2 2
    3 3
    1 2
    2 3
    1 3
    */
  • 相关阅读:
    ios开发-单例抽取宏
    ios开发- NSOperation高级功能
    ios开发-NSOperation介绍
    ios开发,多线程简介
    ios 图片水印 (代码)
    ios 截屏(代码)
    ios 图片剪裁(代码)
    第06组 每周小结 (3/3)
    第06组 每周小结 (2/3)
    第06组 每周小结 (1/3)
  • 原文地址:https://www.cnblogs.com/dyzll/p/7887249.html
Copyright © 2011-2022 走看看