Chinaunix首页 | 论坛 | 博客
  • 博客访问: 198238
  • 博文数量: 67
  • 博客积分: 2970
  • 博客等级: 少校
  • 技术积分: 685
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-23 11:36
文章分类

全部博文(67)

文章存档

2012年(2)

2011年(19)

2010年(46)

我的朋友

分类: C/C++

2010-09-20 15:03:24

 

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

int pow[10005];
int pre[10005];
vector<int> map[10005];

struct Node
{
    char s;
    int a,b,ans;
};
Node node[50005];


int find(int x)
{
    if(pre[x]==x) return x;
    pre[x]=find(pre[x]);
    return pre[x];
}

void merge(int x1,int x2)
{
    int root1=find(x1);
    int root2=find(x2);
    if(root1==root2) return ;
    if(pow[root1]>pow[root2]) pre[root2]=root1;
    else if(pow[root1]<pow[root2]) pre[root1]=root2;
    else
    {                                
        if(root1>root2) pre[root1]=root2;
        else pre[root2]=root1;
    }
}

int main()
{
    int n;
    bool first=true;
    while(scanf("%d",&n)!=EOF)
    {
        if(first) first=false;else printf("\n");
        for(int i=0;i<n;i++)
        {
            scanf("%d",&pow[i]);
            pre[i]=i;
            map[i].clear();
        }

        int m;
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {    
            int a,b;
            scanf("%d%d",&a,&b);
            if(a>b){int temp=a;a=b;b=temp;} //规定方向以避免重复
            map[a].push_back(b);
        }

        int q;
        scanf("%d",&q);
        char str[10];
        for(int i=0;i<q;i++)        
        {
            scanf("%s",str);
            if(str[0]=='q')
            {
                int a;
                scanf("%d",&a);
                node[i].a=a;
                node[i].b=0;
                node[i].s='q';
            }
            else
            {
                int a,b;
                scanf("%d%d",&a,&b);
                if(a>b){int temp=a;a=b;b=temp;}
                node[i].a=a;
                node[i].b=b;
                node[i].s='d';

                for(vector<int>::iterator it=map[a].begin();it!=map[a].end();it++)
                {
                    if(*it>=0&&*it==b)
                    {
                        *it=-1;break;
                    }
                }
            }
        }

        for(int i=0;i<n;i++)
        {
            for(vector<int>::iterator it=map[i].begin();it!=map[i].end();it++)
            {
                if(*it>=0) merge(i,*it);
            }
        }

        for(int i=q-1;i>=0;i--)
        {
            if(node[i].s=='q')
            {
                int root=find(node[i].a);
                node[i].ans=pow[root]>pow[node[i].a]?root:-1;
            }
            else
            {
                merge(node[i].a,node[i].b); //只要两点位于同一集合就说明其是连通的
            }
        }

        for(int i=0;i<q;i++)
            if(node[i].s=='q') printf("%d\n",node[i].ans);
    }
    return 0;
}


总结:


很巧妙的一道并查集~~先把所有的命令存起来,根据最终状态的构图,将每一个连通分量转化成

一个集合,树根是能量最大的星球,若存在多个能量最大的星球,则取编号最小的星球,之后逆

向读取每个命令,若为查询则比对树根和该星球的能量大小,若是消边则并入集合,因为是逆向

处理,该命令之前的构图中存在这两个星球的连接,因而是相反的操作。
阅读(940) | 评论(0) | 转发(0) |
0

上一篇:pku1182 食物链

下一篇:pku1456 Supermarket

给主人留下些什么吧!~~