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;
}