您的位置:首页 > 其它

zoj3261 并查集---略有变形

2011-07-20 23:34 183 查看
题意:有n个星球,每个星球有一定的power值,某些星球是直接或间接相连的。。。当某个星球想求助时会找到相连的里面的power值最大而且大于自己的一个星球。。。先在给定这些power值并给定两两相连的信息,然后又q个操作,destroy a b是删除a b直接相连的边(保证存在),query a求向谁求助,如果不能求助输出-1 。。。

这题是miaowu做的时候给我做的。。。
本来还没想法,他提醒的我哈。。比较巧妙的是先将相连信息和操作信息存下来,从后往前推就成了裸的并查集了。。。
但是存两两关系不大好存。。只能想到用vector存。。。(话说感觉理论上讲如果出变态数据的话是会超时的哈)。。。。
中间一个判断出错wa了几次。。。

代码:

#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;

const int N=50010;
int a
, n, m, q, f
, x1
, y1
, ans
, ansn;
vector<int> ma
;
char s[20];

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

void unionset(int x, int y)
{
int fx = findset(x);
int fy = findset(y);
if(fx!=fy)
{
if(a[fx]>a[fy])
f[fy] = fx;
else if(a[fy]>a[fx])
f[fx] = fy;
else if(fx<fy)
f[fy] = fx;
else
f[fx] = fy;
}
}

int main()
{
int i, j, k, x, y, tmp;
vector<int>::iterator it;
scanf("%d", &n);
while(1)
{
for(i=0; i<n; i++)
scanf("%d", &a[i]);
scanf("%d", &m);

for(i=0; i<m; i++)
{
scanf("%d%d", &x, &y);
if(x>y)
swap(x, y);
ma[x].push_back(y);
}
scanf("%d", &q);
for(i=0; i<q; i++)
{
scanf("%s", s);
if(s[0]=='q')
{
scanf("%d", &y1[i]);
x1[i] = -1;
}
else
{
scanf("%d%d", &x1[i], &y1[i]);
if(x1[i]>y1[i])
swap(x1[i], y1[i]);
for(it=ma[x1[i]].begin(); it!=ma[x1[i]].end(); it++)
if(*it==y1[i])
{
*it = -1;
//break;
}
}
}
for(i=0; i<=n; i++)
f[i] = i;
for(i=0; i<n; i++)
{
for(it=ma[i].begin(); it!=ma[i].end(); it++)
if(*it!=-1)
{
unionset(i, *it);
//printf("%d %d..\n", i, *it);
}
}
ansn = 0;
for(i=q-1; i>=0; i--)
{
if(x1[i]==-1)
{
tmp = findset(y1[i]);
if(a[tmp]!=a[y1[i]]) //这个地方原来写成了tmp!=y1[i]。。。wa了。。。
ans[ansn++] = tmp;
else
ans[ansn++] = -1;
}
else
unionset(x1[i], y1[i]);
}
for(i=ansn-1; i>=0; i--)
printf("%d\n", ans[i]);

for(i=0; i<n; i++)
ma[i].clear();
if(scanf("%d", &n)!=EOF)
printf("\n");
else
break;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: