zoj 3261 Connections in Galaxy War

来源:互联网 发布:ubuntu 安装jdk1.8 编辑:程序博客网 时间:2024/06/10 16:30

点击打开链接zoj 3261

思路: 带权并查集
分析:
1 题目说的是有n个星球0~n-1,每个星球都有一个战斗值。n个星球之间有一些联系,并且n个星球之间会有互相伤害
2 根本没有思路的题,看了网上的思路才知道是逆向并查集。如果我们按照正常的并查集来做,以战斗值最大为根节点的话,当询问的时候很容易,但是碰到删除边的时候就很困难了,所以这里才用逆向的并查集思路
3 我们先把所有的输入保存,然后我们可以这么考虑,从后面往前面枚举q次条件,如果是destroy我们认为是加边,这样的话就很好维护并查集了
4 但是这边我们还要考虑初始的状态,由于涉及到删边而且不一定是删除所有的边,所以我们只要在m个关系里面扣除要删除的边,然后建立集合做为初始的状态

代码:

#include<map>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int MAXN = 50010;struct Node{    int mark;    int x;    int y; };Node node[MAXN];Node edge[MAXN];int n , m , q;int val[MAXN];int father[MAXN];int ans[MAXN];map<int , int>mp;void init(){    mp.clear();    for(int i = 0 ; i < n ; i++)        father[i] = i;}int find(int x){    if(father[x] != x)        father[x] = find(father[x]);     return father[x];}void Union(int x , int y){    int fx = find(x);     int fy = find(y);     if(fx != fy){        if(val[fx] > val[fy])            father[fy] = fx;        else if(val[fx] < val[fy])            father[fx] = fy;        else{            if(fx < fy)                 father[fy] = fx;            else                father[fx] = fy;        }    }}void solve(){    for(int i = 0 ; i < m ; i++){        if(mp[edge[i].x*MAXN+edge[i].y])            continue;        Union(edge[i].x , edge[i].y);    }    int pos = 0;    for(int i = q-1 ; i >= 0 ; i--){        if(node[i].mark == 0){            int fx = find(node[i].x);             // 这边不能写成的node[i].x != fx;            // 因为有可能跟节点和它的值相同            if(val[node[i].x] >= val[fx])                ans[pos++] = -1;            else                ans[pos++] = fx;        }        else            Union(node[i].x , node[i].y);    }    for(int i = pos-1 ; i >= 0 ; i--)        printf("%d\n" , ans[i]);}int main(){    int x , y;    char str[10];    bool first = true;     while(scanf("%d" , &n) != EOF){        if(first)            first = false;        else            puts("");        for(int i = 0 ; i < n ; i++)             scanf("%d" , &val[i]);        init();        scanf("%d" , &m);         for(int i = 0 ; i < m ; i++){            scanf("%d%d" , &edge[i].x , &edge[i].y);            if(edge[i].x > edge[i].y)                swap(edge[i].x , edge[i].y);        }        scanf("%d" , &q);         for(int i = 0 ; i < q ; i++){            scanf("%s" , str);             if(str[0] == 'q'){                scanf("%d" , &node[i].x);                node[i].mark = 0;            }            else{                scanf("%d%d" , &node[i].x , &node[i].y);                if(node[i].x > node[i].y)                    swap(node[i].x , node[i].y);                node[i].mark = 1;                mp[node[i].x*MAXN+node[i].y] = 1;            }        }        solve();    }    return 0;}


原创粉丝点击