bzoj3562: [SHOI2014]神奇化合物

又是玄学的一天~

首先,这题做法就很玄学,考虑到点和询问都很少,那么很多边都是没有改动的,那么可以离线用并查集缩点,然后爆搜求解。

假如只是这样还好吧,尴尬就在于我跑数据前面3个点挂了??黑人问号

然后一怒之下特判,假如边数<10000那我就不缩点,直接爆力搞!

A了~ 真的A了。。。

这个故事告诉我们,猜证结合,爆正乱搞,天下大同。。。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int n,m;
struct init
{
    int x,y,op;
}h[210000],q[11000];int hlen,qlen;
bool pc[5100][5100];
char ss[10];
void sc()
{
    hlen=0;
    memset(pc,false,sizeof(pc));
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if(pc[x][y]==false)
        {
            pc[x][y]=true;pc[y][x]=true;
            hlen++;
            h[hlen].x=x,h[hlen].y=y;
        }
    }

    scanf("%d",&qlen);
    for(int i=1;i<=qlen;i++)
    {
        scanf("%s",ss+1);
        if(ss[1]==‘A‘)
        {
            scanf("%d%d",&q[i].x,&q[i].y),q[i].op=1;
            pc[q[i].x][q[i].y]=false;
            pc[q[i].y][q[i].x]=false;
        }
        else if(ss[1]==‘D‘)
        {
            scanf("%d%d",&q[i].x,&q[i].y),q[i].op=2;
            pc[q[i].x][q[i].y]=false;
            pc[q[i].y][q[i].x]=false;
        }
        else q[i].op=3;
    }
}

int fa[5100];
int findfa(int x)
{
    if(fa[x]==x)return x;
    fa[x]=findfa(fa[x]);return fa[x];
}
void shrink()
{
    for(int i=1;i<=n;i++)fa[i]=i;
    if(m>10000)
    {
        for(int x=1;x<=n;x++)
            for(int y=1;y<=n;y++)
                if(pc[x][y]==true)
                {
                    int fx=findfa(x),fy=findfa(y);
                    if(fx!=fy)fa[fx]=fy;
                }
    }
}

//-----------init------------------------

struct node
{
    int x,y,next;bool ch;
}a[4100000];int len,last[5100];
int eid[5100][5100];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
    a[len].ch=false;
    eid[x][y]=len;
}
void cut(int x,int y)
{
    if(eid[x][y]!=-1)
    {
        a[eid[x][y]].ch=true;
        eid[x][y]=-1;
    }
}

//------------edge------------------------

int tim,v[5100];
void dfs(int x)
{
    v[x]=tim;
    for(int k=last[x];k;k=a[k].next)
    {
        if(a[k].ch==false)
        {
            int y=a[k].y;
            if(v[y]!=tim)dfs(y);
        }
    }
}

int main()
{
    freopen("compound.in","r",stdin);
    freopen("compound.out","w",stdout);

    scanf("%d%d",&n,&m);
    sc();shrink();
    memset(eid,-1,sizeof(eid));
    for(int i=1;i<=hlen;i++)
    {
        int x=findfa(h[i].x),y=findfa(h[i].y);
        if(x!=y&&eid[x][y]==-1) ins(x,y), ins(y,x);
    }

    tim=0;memset(v,0,sizeof(v));
    for(int i=1;i<=qlen;i++)
    {
        if(q[i].op==1)
        {
            int x=findfa(q[i].x),y=findfa(q[i].y);
            if(eid[x][y]==-1)
                ins(x,y),ins(y,x);
        }
        else if(q[i].op==2)
        {
            int x=findfa(q[i].x),y=findfa(q[i].y);
            cut(x,y),cut(y,x);
        }
        else
        {
            int ans=0;tim++;
            for(int i=1;i<=n;i++)
            {
                int x=findfa(i);
                if(v[x]!=tim) dfs(x), ans++;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/AKCqhzdy/p/8782557.html

时间: 2024-09-29 22:09:27

bzoj3562: [SHOI2014]神奇化合物的相关文章

BZOJ 3562: [SHOI2014]神奇化合物 并查集+dfs

点击打开链接 注意到20w条边,但是询问只有1w,所以有很多边是从头到尾不变的. 首先离线处理,将从未删除的边缩点,缩点后的图的点数不会超过2w,对于每一次add或者delete,直接dfs看是否能从a走到b,然后维护一个ans. 数据不强,不然这种复杂度起码要跑10s.. #include<stdio.h> #include<iostream> #include<algorithm> #include<cstring> using namespace st

大视野3562 [SHOI2014]神奇化合物

http://www.lydsy.com/JudgeOnline/problem.php?id=3562 1 //Accepted 6020 kb 1012 ms 2 //由于题目的特殊要求:然而,令科学家们大为惊异的是,SHTSC 在变化过程中始终保持着一种特殊的性质: 3 //即不存在这样的原子序列 a1,a2,...,an(n>3)满足 a1 与 a2.a2 与 4 //a3........an-1 与 an 以及 an 与 a1 都通过化学键相连,但它们之间却没有其他化学键相连的情况.

BZOJ 3562 SHOI2014 神奇化合物 暴力

题目大意:维护一张弦图,支持加边.删边和询问图中有多少个联通块 暴力题233 直接做O(qn+qm)会挂 因此我们预先将m条边中自始至终不会被删除的边用并查集缩点 这样图中的边就只有O(q)条 暴力即可 时间复杂度O(nq+q^2) 很疑惑为什么要给一张弦图- - 去找了下没看到类似于动态弦图的东西- - #include <map> #include <vector> #include <cstdio> #include <cstring> #includ

【BZOJ3562】【SHOI2014】神奇化合物 特技

广告: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44016219"); } 题解: 一开始让我写这道题,其实我是,是拒绝的. 我跟大爷讲,我拒绝,因为,其实我,根本搞不懂这个时间复杂度. 大爷跟我讲,敲时加特技,代码很短很快很好. 加了30行特技之后呢,代码DUANG~~~ 后来我其

[BZOJ 3553][SHOI2014]三叉神经树

传送门(下面也有题面) 题目大意: 一颗有根树,每个非叶子节点都有三个子节点,每个节点的权为0/1. 每个节点的权 取决于其所有子节点中 哪种权出现的次数更多. 有若干次询问,每次询问修改一个叶子节点的权,然后输出修改后根节点的权. 给出叶子节点初始值. 解法:树链剖分+线段树 叶子节点和非叶子节点的性质不同,为了省却麻烦,我们把叶子节点去掉, 每次修改叶子节点就直接修改其父亲.以下的“叶子节点”均指处理后的树的叶子节点. 如果用num[]记录每个节点的权为1的子节点个数, 那么当num[i]>

bzoj3696 化合物

Description 首长NOI惨跪,于是去念文化课了.现在,他面对一道化学题.    这题的来源是因为在一个奇怪的学校两个化竞党在玩一个奇怪的博弈论游戏.这个游戏很蛋疼,我相信你们也没有兴趣听.    由于这个游戏涉及博弈论,因此化竞的同学就要求首长求一个类似SG函数的值.    他们手中有一种非常神奇的化合物,它的分子由N个原子组成(不要在意一个原子可能和及其多个原子成键这个细节).这个分子构成一个树结构,1号分子为根.    若两个原子i.j到它们的最近公共祖先的距离分别是Li和Lj,定

【BZOJ3696】化合物 树形DP+暴力

[BZOJ3696]化合物 Description 首长NOI惨跪,于是去念文化课了.现在,他面对一道化学题.    这题的来源是因为在一个奇怪的学校两个化竞党在玩一个奇怪的博弈论游戏.这个游戏很蛋疼,我相信你们也没有兴趣听.    由于这个游戏涉及博弈论,因此化竞的同学就要求首长求一个类似SG函数的值.    他们手中有一种非常神奇的化合物,它的分子由N个原子组成(不要在意一个原子可能和及其多个原子成键这个细节).这个分子构成一个树结构,1号分子为根.    若两个原子i.j到它们的最近公共祖

【bzoj3696】化合物 树形dp

题目描述 首长NOI惨跪,于是去念文化课了.现在,他面对一道化学题.这题的来源是因为在一个奇怪的学校两个化竞党在玩一个奇怪的博弈论游戏.这个游戏很蛋疼,我相信你们也没有兴趣听.由于这个游戏涉及博弈论,因此化竞的同学就要求首长求一个类似SG函数的值.他们手中有一种非常神奇的化合物,它的分子由N个原子组成(不要在意一个原子可能和及其多个原子成键这个细节).这个分子构成一个树结构,1号分子为根.    若两个原子i.j到它们的最近公共祖先的距离分别是Li和Lj,定义它们的Aij值为:Aij=Li  x

[FJSC2014]化合物

[题目描述] 首长NOI惨跪,于是去念文化课了.现在,他面对一道化学题. 这题的来源是因为在一个奇怪的学校两个化竞党在玩一个奇怪的博弈论游戏,这个游戏很蛋疼,我相信你们也没有兴趣听. 由于这个游戏涉及博弈论,因此化竞的同学就要求首长求一个类似SG函数的值. 他们手中有一种非常神奇的化合物,它的分子由N个原子组成(不要在意一个原子可能和及其多个原子成键这个细节).这个分子构成了一个树结构,1号分子为根. 若两个原子i.j到它们的最近公共祖先的距离分别是li和lj,定义它们的Aij值为: Aij =