zoukankan      html  css  js  c++  java
  • ZOJ 3261 Connections in Galaxy War(逆向并查集)

    参考链接:

       http://www.cppblog.com/yuan1028/archive/2011/02/13/139990.html

      http://blog.csdn.net/roney_win/article/details/9473225

    题意:N个星球,编号从0到N-1。每个星球有一个战斗力power,且这N个星球之间建有一些通道,可以相互联系,在星球大战中,一些星球要向和自己联通的星球中power最强且大于自己的星球求救,且在星球大战中会有一些通道被损坏。

      两种操作:破坏a和b之间的通道;a星球该向谁求救。

    逆向并查集:

      与并查集不同,给出一个图中原有的一些边,然后给出操作,操作不是向图中添加边,而是在已有的边上,将边删除。

      对于该种情况,需要首先读入所有操作,把要求删除的边全部删除,再按照从后往前的顺序处理操作,这样删边操作转化为了添边的操作。

    思路:我们先输入所有数据,即所谓的离线输入,将星球大战之后的状态作为初始状态,进行并查集的操作,遇到destroy时,就恢复a到b之间的通道,那么就很容易维护根节点的性质了,这题就变得很简单了。

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn=10010;
    int father[maxn];
    long long power[maxn];
    int n,m,q;
    int ans[maxn*5];  //存储最后要输出的答案
    
    struct Edge{
        int u,v,flag;  //u、v表示边的端点,u<=v;flag=0表示改变被删除
    
        //将u从小到大排序,若u相同时,按v从小到大排序
        bool operator < (const Edge tmp)const {
            if(u==tmp.u)
                return v<tmp.v;
            return u<tmp.u;
        }
    } edge[2*maxn];
    
    //先把所有的询问都存储下来
    struct  Query{
        int k,a,b; //k=1表示操作是询问,k=2表示操作是删边
    }query[maxn*5];
    
    struct Node {
        int u;  //u代表集合中具有最大能力值的点的编号
        long p; //p代表集合中点的最大能力值
    } node[maxn];
    
    void init() {
        for(int i=0; i<n; i++) {
            father[i]=i;
            node[i].u=i;
            node[i].p=power[i];
        }
    }
    
    int find_root(int x) {
        if(father[x]!=x)
           father[x]=find_root(father[x]);
        return father[x];
    }
    
    void Union(int x,int y) {
        father[y]=x;
        if(node[x].p<node[y].p){
            node[x].p=node[y].p;
            node[x].u=node[y].u;
        }
        else if(node[x].p==node[y].p && node[x].u>node[y].u){
            node[x].u=node[y].u;
        }
    }
    //二分查找边,a<=b
    void findEdge(int a,int b){
        int mid,mins=0,maxs=m-1;
        while(mins<=maxs){
            mid=(mins+maxs)>>1;
            if(a==edge[mid].u && b==edge[mid].v){
                edge[mid].flag=0;
                return;
            }
            if(a<edge[mid].u){
                maxs=mid-1;
            }
            else if(a>edge[mid].u){
                mins=mid+1;
            }
            else{
                if(b<edge[mid].v){
                    maxs=mid-1;
                }
                else{
                    mins=mid+1;
                }
            }
        }
    }
    int main() {
        int a,b,blank=0;
        char ch[10];
        while(scanf("%d",&n)!=EOF) {
            memset(vis,0,sizeof(vis));
            if(blank==0)
                blank=1;
            else
                puts("");
            for(int i=0;i<n;i++){
                scanf("%I64d",&power[i]);
            }
            scanf("%d",&m);
            for(int i=0; i<m; i++) {
                scanf("%d%d",&a,&b);
                if(a<b) {
                    edge[i].u=a;
                    edge[i].v=b;
                    edge[i].flag=1;
                } else {
                    edge[i].u=b;
                    edge[i].v=a;
                    edge[i].flag=1;
                }
            }
            sort(edge,edge+m); //一开始忘记排序了
            scanf("%d",&q);
            for(int i=0; i<q; i++) {
                scanf("%s",ch);
                if(ch[0]=='q') {
                    scanf("%d",&a);
                    query[i].k=1;
                    query[i].a=a;
                    query[i].b=-1;
                }
                else{
                    scanf("%d%d",&a,&b);
                    int t;
                    if(a>b){
                        t=a;a=b;b=t;
                    }
                    findEdge(a,b);
                    query[i].k=2;
                    query[i].a=a;
                    query[i].b=b;
                }
            }
            int x,y;
            init();
            for(int i=0;i<m;i++){
                if(edge[i].flag==1){
                    x=find_root(edge[i].u);
                    y=find_root(edge[i].v);
                    if(x!=y){
                        Union(x,y);
                    }
                }
            }
            int u,v;
            for(int i=q-1;i>=0;i--){
                if(query[i].k==1){
                    x=find_root(query[i].a);
                    if(node[x].p>power[query[i].a]){
                        ans[i]=node[x].u;
                    }
                    else{
                        ans[i]=-1;
                    }
                }
                else{
                    u=query[i].a;
                    v=query[i].b;
                    x=find_root(u);
                    y=find_root(v);
                    if(x!=y){
                        Union(x,y);
                    }
                    ans[i]=-2;
                }
            }
            for(int i=0;i<q;i++){
                if(ans[i]==-2)
                    continue;
                printf("%d
    ",ans[i]);
            }
        }
        return 0;
    }
  • 相关阅读:
    汉字编码问题
    C语言创建UTF8编码文本文件
    Know more about shared pool subpool
    SCN Headroom与时光倒流到1988年的Oracle数据库
    Know more about Enqueue Deadlock Detection
    11g新特性:RDBMS Component TRACE
    了解你所不知道的SMON功能(十一):OFFLINE UNDO SEGMENT
    了解11g OCM
    Bulk Collect/FORALL的性能测试
    【推荐】DBA必须了解的11g中的一些变化
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3303484.html
Copyright © 2011-2022 走看看