Connections in Galaxy War
思路:
反向操作,宇宙從無開始。
- 先離線。
- 由於要反向,可以map記錄哪條邊要被破壞.
- 在讀完數據後,把讀入的邊沒被破壞的先建好,之後就開始反向操作,並做好記錄。
- 並查集裏的merge(由於要B的能量要大於A的能量,所以每次操作時把能量大的作爲祖先,如果能量相同,那麼就小號作爲祖先)
- 之後開始反向詢問,如果是destroy那麼就建邊,
- 否則就詢問:查看 B(祖先的)能量和 A的能量(因爲A可能和祖先B有相同的能量)p【B】> p【A】那麼就可以救援,ans【i】=B;
反思:
- 一開始每考慮到可能A和祖先相同能量,是救援不了的。
- 沒考慮到可能讀入數據(q次詢問裏的destory 和 m條邊的順序可能不同,記錄可能有誤差,所以把小的序號放前面)
- 多case裏每個輸出一個空格,由於是文件讀寫,所以可以這樣。
if(flag)flag=false;
else printf("\n");
For(i,1,q)if(!ans[i].flag)printf("%d\n",ans[i].out);
- map裏可以用pair,使用時像這樣。
ans[i].a=a;ans[i].b=b;
ma[mp(a,b)]=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;
}