Connections in Galaxy War----zoj3261

题目链接:

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3261

题意:有n个星球编号为0—n-1;能量分别为p[i];有m句话,每句话输入a,b表示星球a和星球b可以相通的;

但是由于银河之战,破坏了一些通道

接下来有Q句话:destroy a b代表ab之间的通道被破坏;

        query a代表求a可以向哪个星球求助,并输出编号,如果没有就输出-1;

各个星球只像能量值比自己大的星球求助,而且是尽量找到最大能量值的星球求助。

如果有多个能量值一样的星球可以求助,则找编号小的。

思路:

   输入时记录每一条边

        记录每一个操作和销毁的边。

        输入结束后先用并查集加入所有没有被销毁的边

        然后再逆序操作记录结果,此时遇到 destroy 则加入销毁的边 ,遇到 query 直接查找即可。

         最终逆序输出结果。

   不同的测试数据有空行。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<map>
#define N 50010
#define INF 0xfffffff
using namespace std;

struct node
{
    int op,x,y;/// 1代表查询,2代表破坏;
} a[N],b[N];

int f[N], p[N], n, m, ans[N];

map<int,int> maps[N];

int Find(int x)
{
    if(x != f[x])
        f[x] = Find(f[x]);
    return f[x];
}

void Union(int x, int y)
{
    int px = Find(x);
    int py = Find(y);
    ///合并的时候要向能量较大的那边合并,如果能量相等向编号小的那边合并;
    if(p[px] > p[py])
        f[py] = px;
    else if(p[px] < p[py])
        f[px] = py;
    else
    {
        if(px <= py)
            f[py] = px;
        else
            f[px] = py;
    }
}
void Init()
{
    int i;
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));
    for(i=0; i<= n;i++)
    {
        maps[i].clear();
        f[i] = i;
        p[i] = 0;
    }
}
int main()
{
    char str[20];
    int i, j, y, x, Q, flag=0;
    while(scanf("%d", &n)!=EOF)
    {
        Init();
        
        for(i=0; i<n; i++)
            scanf("%d", &p[i]);
            
        scanf("%d", &m);
        for(i=0; i<m; i++)
        {
            scanf("%d%d", &x, &y);
            if(x > y) swap(x, y);
            
            b[i].x = x;b[i].y = y;
            
            maps[x][y] = 1;//代表x和y之间的通道存在;
        }

        scanf("%d", &Q);
        for(i=0; i<Q; i++)
        {
            scanf("%s", str);
            if(str[0] == 'q')
            {
                scanf("%d", &x);
                a[i].op = 1;a[i].x = x;
            }
            else
            {
                scanf("%d %d", &x, &y);
                if(x > y) swap(x, y);
                
                maps[x][y] = 0;///x和y之间的路没路;
                
                a[i].op = 2;a[i].x = x;a[i].y = y;                
            }
        }
        for(i=0; i<m; i++)///把没有被破坏的边放到一起;
        {
            if(maps[b[i].x][b[i].y]==1)
                Union(b[i].x, b[i].y);
        }
        j=0;
        for(i=Q-1; i>=0; i--)///逆序处理每个操作;
        {
            if(a[i].op == 1)
            {
                int px = Find(a[i].x);
                if(p[px] > p[a[i].x])///只能向比自己能量大的求助;
                    ans[j++] = px;
                else
                    ans[j++] = -1;
            }
            else if(a[i].op == 2)
                Union(a[i].x, a[i].y);
        }
        
        if(flag)printf("
");
        flag = 1;
        
        for(i=j-1; i>=0; i--)
            printf("%d
", ans[i]);

    }
    return 0;
}
View Code

 

原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4679072.html