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

Connections in Galaxy War ZOJ - 3261 离线操作+逆序并查集 并查集删边

时间:2020-02-02 01:29:08      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:ios   直接   wap   ==   节点   scan   ems   amp   clear   

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<map>
#include<vector>
#define cle(a) memset(a,0,sizeof(a))
using namespace std;
const int N=50000+10;
int w[20100];
bool cmp(int a,int b){
    return a>b;
}
int n,q,m,fa[N],arr[25000][2],ans[60000];
vector<pair<int,int> >vp;
map<pair<int,int>,int>mp;
void init(){
    for(int i=0;i<=n+5;i++)fa[i]=i;
    mp.clear();
    vp.clear();
    cle(ans);
    cle(arr);
}
int find(int x){
    if(fa[x]!=x)
        fa[x]=find(fa[x]);
    return fa[x];
}
void Union(int a,int b)
{
    int x=find(a);
    int y=find(b);
    if(x==y)
        return;
    if(w[x]>w[y])
        fa[y]=x;
    else if(w[x]<w[y])
        fa[x]=y;
    else{    //这里 的判断要注意
        if(x<y)
            fa[y]=x;
        else 
            fa[x]=y;
    }
}
int main()
{
    int mark=0;
    while(cin>>n)
    {
        if(mark)
            printf("\n");
        init();
        //每个点的价值 
        for(int i=0;i<n;i++)
            scanf("%d",&w[i]);
        scanf("%d",&m);
        //
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&arr[i][0],&arr[i][1]);
            //大的在前面,为后面建边做准备 
            if(arr[i][0]>arr[i][1])
                swap(arr[i][0],arr[i][1]);
        }
        scanf("%d",&q);
        char s[20];
        int t,p;
        for(int i=1;i<=q;i++)
        {
            scanf("%s",s);
            if(s[0]==q)
            {
                scanf("%d",&t);
                vp.push_back({t,-2});
            }
            else{
                scanf("%d%d",&t,&p);
                if(t>p)
                    swap(t,p);
                //标记已经建过边了,相当于标记要被拆掉 
                mp[{t,p}]=1;
                vp.push_back({t,p});
            }
        }
        //先把不会被拆掉的边建上 
        for(int i=1;i<=m;i++)
            if(!mp[{arr[i][0],arr[i][1]}])
                Union(arr[i][0],arr[i][1]);
        //然后从后往前遍历操作
        //如果是查询,直接做 
        //如果是拆边,就建上 
        int j=0;
        for(int i=vp.size()-1;i>=0;i--){
            int a=vp[i].first;
            int b=vp[i].second;
            //如果是查询 
            if(b==-2)
            {
                //找到父节点 
                int c=find(a);
                //如果相同,就是-1 
                if(w[a]>=w[c])
                    c=-1;
                //保存答案 
                ans[j++]=c;
            }
            else 
                Union(a,b);
        }
        for(int i=j-1;i>=0;i--)
            printf("%d\n",ans[i]);
        mark=1;
    }
    return 0;
}

 

Connections in Galaxy War ZOJ - 3261 离线操作+逆序并查集 并查集删边

标签:ios   直接   wap   ==   节点   scan   ems   amp   clear   

原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12250677.html

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