玲珑学院OJ 1072 Capture【并查集+优先队列】

1072 - Capture

Time Limit:15s Memory Limit:1024MByte

Submissions:545Solved:180

DESCRIPTION

In a city capture game, Mr. Van owns a Empire with a capital city ( marked 1 ). Initially, Mr. Van's Empire had the capital only. All other cities were captured by him in the game and each next captured city was marked the next natural number (2, 3, ...).

In order to make his Empire connected, each newly captured city was connected by a road to exactly one of the cities of his Empire at the moment of capture.

Some of the cities were disconnecting from his Empire and were never captured again. In order to disconnect from the empire, enemies destroy the road that was built to connect them with the Empire. Some other cities also may become disconnected from the Empire at that moment and the Empire loses them too.

To protect his cities more effectively, Mr.Van reconstructed the whole history of his Empire and represented it as a sequence of events: captures and disconnections. After each event he needs to know the number of the city which is the most remote from his capital. The distance from one city to another is measured as the minimal amount of roads that one need to pass in order to get from one city to another. If there are several most remote cities, he take the smallest number one.

Given the history of his Empire, your job is to tell which city is the most remote after each event.

INPUT
The first line is a single integer TT, indicating the number of test cases.For each test case:
The first line of the input contains the integer number N (1N100000)N (1≤N≤100000) number of historical events. The description of events in chronological order follows starting from the second line. Each event is written in a single line. If the event is 'capture', then it's written as "+V""+V" where V is the number of the city in the Empire that new city got connected to (the new city marks next integer number in the sequence of city numbers). Disconnections are written as "V""−V" which means that the city V is disconnected from the Empire.
All input data is correct, only a city that is connected to the Empire can be disconnected, new cities will be connected only to the ones that belong to the Empire, the capital is never disconnected.
OUTPUT
For each event from the input file, print the city's marked number which is the most remote from the capital. In case several solutions exist, output the minimal one.
SAMPLE INPUT
1
5
+1
+2
+1
-2
+4
SAMPLE OUTPUT
2
3
3
4
5


题目大意:


1号作为国王呆的地方,他永远不会被“-”。

一共有两种操作:

①+v,表示把一个新的城市连接到城市v上(按照2.3.4.5........的顺序连接)。

②-v,表示把城市v摧毁,那么对应连接在v之后的城市也相当于被摧了。

保证城市1一定不回被摧毁。

每次操作结束,询问距离1号城市最远的城市编号,如果有多个距离相等的点,取编号最小的。


思路:


1、对于两种操作:

①+v.我们只要将新的城市(编号设定为:new)直接连在城市v上即可:f【new】=v,过程不要有压缩路径操作。

相关距离问题,很好处理,我们设定dis【1】=0,那么对应连接在城市v上的新城市的距离为:dis【new】=dis【v】+1;

②-v.我们只要将城市v隔离出来即可f【v】=v;


2、关于查询:

因为随着点的增加,我们要对已存在的各个点到1号城市的距离进行一个优先级排序,而且操作频繁,所以我们这里引入一个优先队列,维护距离1号最远且编号最小的那个点。

同时问题有个坑点,当1号整个变成一个孤立点的时候,输出为1(这里有可能忘记了).


Ac代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct node
{
    int u,len;
    friend bool operator <(node a,node b)
    {
        if(a.len!=b.len)
        return a.len<b.len;
        else return a.u>b.u;
    }
}nod;
int dis[400000];
int f[400000];
int find(int a)
{
    int r=a;
    while(f[r]!=r)
    r=f[r];
    return r;
}
int merge(int a,int b)
{
    f[b]=a;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        priority_queue<node>s;
        int n;
        int now=2;
        scanf("%d",&n);
        memset(dis,0,sizeof(dis));
        for(int i=1;i<=n+10;i++)f[i]=i;
        nod.u=1;
        nod.len=0;
        s.push(nod);
        while(n--)
        {
            char a[1550];
            scanf("%s",a);
            int u=0;
            for(int i=1;i<strlen(a);i++)
            {
                u=u*10+a[i]-'0';
            }
            if(a[0]=='+')
            {
                dis[now]=dis[u]+1;
                nod.u=now;
                nod.len=dis[now];
                s.push(nod);
                merge(u,now);
                now++;
            }
            else
            {
                f[u]=u;
            }
            while(!s.empty())
            {
                nod=s.top();
                if(find(nod.u)==1)
                {
                    printf("%d\n",nod.u);
                    break;
                }
                else s.pop();
            }
        }
    }
}











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值