[kuangbin帶你飛]專題五 並查集 zoj3261(反向並查集+map記錄要摧毀邊)

Connections in Galaxy War

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

思路:

反向操作,宇宙從無開始。

  1. 先離線。
  2. 由於要反向,可以map記錄哪條邊要被破壞.
  3. 在讀完數據後,把讀入的邊沒被破壞的先建好,之後就開始反向操作,並做好記錄。
  4. 並查集裏的merge(由於要B的能量要大於A的能量,所以每次操作時把能量大的作爲祖先,如果能量相同,那麼就小號作爲祖先)
  5. 之後開始反向詢問,如果是destroy那麼就建邊,
  6. 否則就詢問:查看 B(祖先的)能量和 A的能量(因爲A可能和祖先B有相同的能量)p【B】> p【A】那麼就可以救援,ans【i】=B;

反思

  1. 一開始每考慮到可能A和祖先相同能量,是救援不了的。
  2. 沒考慮到可能讀入數據(q次詢問裏的destory 和 m條邊的順序可能不同,記錄可能有誤差,所以把小的序號放前面)
  3. 多case裏每個輸出一個空格,由於是文件讀寫,所以可以這樣。
	if(flag)flag=false;
        else printf("\n");
        For(i,1,q)if(!ans[i].flag)printf("%d\n",ans[i].out);
  1. map裏可以用pair,使用時像這樣。
	ans[i].a=a;ans[i].b=b;
            ma[mp(a,b)]=1;
  1. strcmp(s,t)當兩串相等時,才放回0

AC

#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#define mp make_pair
#define For(i,x,y) for(register int i=(x); i<=(y); i++)
using namespace std;
const int maxn=1e4+10;
typedef pair<int,int>pa;
struct Querry
{
    int a,b;
    bool flag;//true destory
    int out;
}ans[5*maxn];
map<pa,int>ma;
char s[1000];
int f[maxn],p[maxn],fr[2*maxn], to[2*maxn];
int n,m,q;
int find(int x)
{
    if(x==f[x])return x;
    return f[x]=find(f[x]);
}
void merge(int u,int v)
{
    int uf=find(u), rf=find(v);
    if(p[uf]>p[rf])f[rf]=uf;
    else if(p[uf]==p[rf])
    {
        if(uf<rf)f[rf]=uf;
        else if(uf>rf)f[uf]=rf;
    }
    else f[uf]=rf;
}
void init()
{
    For(i,0,n)f[i]=i;
    ma.clear();
   // ma.empty();
    For(i,0,n-1)scanf("%d", &p[i]);
    scanf("%d", &m);
    int a,b;
    For(i,1,m)
    {
        scanf("%d%d", &a,&b);
        if(a>b)swap(a,b);
        fr[i]=a,to[i]=b;
    }
  //  cout<<"ok"<<endl;
    scanf("%d", &q);
    For(i,1,q)
    {
        scanf("%s",s);
       // cout<<"ok"<<endl;
        if(strcmp(s,"query")==0)
        {
            scanf("%d",&ans[i].a);
            ans[i].flag=false;
        }
        else
        {
            scanf("%d%d", &a,&b);
            if(a>b)swap(a,b);
            ans[i].a=a;ans[i].b=b;
            ma[mp(a,b)]=1;
         //   printf("a=%d, b=%d, %d\n",a, b,ma[mp(a,b)]);
            ans[i].flag=true;
        }
    }
}
void build()
{
    For(i,1,m)
    {
        int id=ma[mp(fr[i],to[i])];
        if(!id)merge(fr[i],to[i]);
    }
}
void solve()
{
    for(int i=q; i>=1; i--)
    {
        if(ans[i].flag)merge(ans[i].a,ans[i].b);
        else
        {
            int fx=find(ans[i].a);
            if(p[ans[i].a]<p[fx])ans[i].out=fx;
            else ans[i].out=-1;
        }
    }
}
int main()
{
    bool flag=true;
    while(~scanf("%d", &n))
    {
        
        init();
        build();
     //   cout<<"ok"<<endl;
        solve();
        if(flag)flag=false;
        else printf("\n");
        For(i,1,q)if(!ans[i].flag)printf("%d\n",ans[i].out);
     //   printf("/n");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章