L - Connections in Galaxy War - zoj 3261

题意:有一个帝国在打仗,敌方会搞一些破坏,总共用N个阵地,每个阵地都有一个武力值,当第一地方收到攻击的时候他可以进行求助,当然求助的对象只能是武力值比他高的,如果求助失败就输出 ‘-1’, 求助成功就输出 帮助对象的的下标,如果有多个相同武力值的阵地输出下标最小的那个。
输入的第一行是N,表示又N个阵地(0到n-1),下面一行输入每个阵地的武力值,接着输入一个M,下面有M行,表示两点可以想通,接着有Q次查询,query 是查询这个点能不能有帮助他的,destroy表示摧毁两点之间的联系,值得注意的是,他所摧毁的一定是存在的路,而输入的时候也没有重复数据(为了是题目简单一些吧)。
分析:由于是中间有摧毁的步骤,而并查集只能两点链接,不能消除,所以只能倒着处理数据,先把所有能摧毁的全部都不链接,把没有摧毁的链接起来,(可以用扩大第二个数的办法来快速查找路),倒着读的时候遇到摧毁就进行建立,这样可以了,不过还要注意值相等的时候按照下标,就是忘了这点才错了好几次,而且数据之间输出一个空行
////////////////////////////////////////////////////////////////

 #include<iostream>

#include<algorithm>
#include<stdio.h>
#include<math.h>
#include< string.h>
#include<queue>
#include<stack>
using  namespace std;

const  int maxn =  20005;
const  int BigNum =  10000;

struct node
{
     int op, u, v; // op等于1代表查询,等于0代表摧毁
}data[maxn* 3]; // 保存查询数据

int f[maxn], val[maxn];
// 为了方便查询,把x值扩大10w倍+y值保存下来,use记录这个路是否被摧毁
int h[maxn], use[maxn];

int Find( int x)
{
     if(f[x] != x)
        f[x] = Find(f[x]);
     return f[x];
}
void Union( int u,  int v)
{
    u = Find(u), v = Find(v);

     if(u != v)
    {
         if(val[u] < val[v])
            f[u] = v;
         else  if(val[u] > val[v]) // 写成了两个一样的。。。。
            f[v] = u;
         else  if(u < v)
            f[v] = u;
         else
            f[u] = v;
    }
}

int main()
{
     int N, t= 0;

     while(scanf( " %d ", &N) != EOF)
    {
         int i, M, u, v, Q;
         char s[ 10];

         for(i= 0; i<N; i++)
        {
            f[i] = i;
            scanf( " %d ", &val[i]);
        }

        scanf( " %d ", &M);

         for(i= 0; i<M; i++)
        {
            scanf( " %d%d ", &u, &v);
             if(u > v)swap(u, v);
            h[i] = u + v*BigNum;
            use[i] =  0;
        }

        sort(h, h+M);

        scanf( " %d ", &Q);

         for(i= 0; i<Q; i++)
        {
            scanf( " %s ", s);

             if(s[ 0] ==  ' d ')
            {
                scanf( " %d%d ", &u, &v);

                 if(u > v)swap(u, v);
                data[i].u = u;data[i].v = v;
                data[i].op =  0;
                 int k = lower_bound(h, h+M, u+v*BigNum) - h;
                use[k] =  1;
            }
             else
            {
                scanf( " %d ", &u);
                data[i].op =  1, data[i].u = u;
            }
        }

         for(i= 0; i<M; i++)
        {
            u = h[i] % BigNum, v = h[i] / BigNum;
             if(use[i] ==  0)
                Union(u, v);
        }

        stack< int>sta;

         for(i=Q- 1; i>= 0; i--)
        {
             if(data[i].op ==  0)
                Union(data[i].u, data[i].v);
             else
            {
                u = Find(data[i].u);

                 if(val[u] <= val[data[i].u])
                    sta.push(- 1);
                 else
                    sta.push(u);
            }
        }

         if(t++)printf( " \n ");
         while(sta.size())
        {
            printf( " %d\n ", sta.top());
            sta.pop();
        }
    }

     return  0;
}
/*
5
1 2 3 4 5
4
0 1
1 2
2 3
3 4
5
query 0
query 1
query 2
query 3
query 4
*/

你可能感兴趣的:(Connection)