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

bzoj3562: [SHOI2014]神奇化合物

时间:2018-04-10 21:48:04      阅读:206      评论:0      收藏:0      [点我收藏+]

标签:namespace   amp   离线   直接   als   com   stdout   mat   find   

又是玄学的一天~

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

假如只是这样还好吧,尴尬就在于我跑数据前面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;
}

 

bzoj3562: [SHOI2014]神奇化合物

标签:namespace   amp   离线   直接   als   com   stdout   mat   find   

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

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