链接:http://www.ifrog.cc/acm/problem/1072?contest=1009&no=1
题意: 有节点1 , n个操作。每个操作可以选择 +V(将当前节点加到V), -V(V节点独立出来)。每次输出在每次操作后到首都1距离最远的城市编号,多个距离相同输出编号最小的城市
输入数据保证正确,每次添加与删除的城市一定是与首都相连的。
分析: 使用并查集+优先队列就可以很好的解决这个问题。注意并查集不能路径压缩。
#include <iostream>
#include <algorithm>
#include <queue>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
using namespace std;
const int N = 100000+10;
struct note
{
int id,x,len;
//不写只读函数就编译不过去,查询无果,求帮助。。
bool operator < (const note &Note) const
{
if(len != Note.len)
return len < Note.len;
return id > Note.id; //距离相等节点节点小的在前面
}
};
note fa[N];
priority_queue<note> que;
int findNum(char *str);
int find_fa(int x);
void union_xy(int x,int y);
int main()
{
int t,n,i,j;
char str[15];
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1; i<N; i++)
fa[i].x = i,fa[i].len = 0,fa[i].id = i;
while(que.empty() != true)
que.pop(); //清空
que.push(fa[1]); 将1节点压进来
int id = 2;
for(int i=2; i<=n+1; i++)
{
scanf(" %s",str);
int num = findNum(str);
if(str[0] == '-')
{
fa[num].x = num;
while(find_fa(que.top().id) != 1)
que.pop();
printf("%d\n",que.top().id);
}
else
{
union_xy(num,id++);
while(find_fa(que.top().x) != 1)
que.pop();
printf("%d\n",que.top().id);
}
}
}
return 0;
}
int find_fa(int x)
{
if(fa[x].x == x)
return x;
return find_fa(fa[x].x); //不能路径压缩
}
void union_xy(int x,int y)
{
fa[y].x = x;
fa[y].len = fa[x].len + 1;
que.push(fa[y]);
}
int findNum(char *str)
{
int len = strlen(str);
int num = 0;
for(int i=1; i<len; i++)
num = num*10 + str[i] - '0';
return num;
}