题目:
题解:
1A辣!!!!
给每个公司建一棵树,就是给每个数组多一维id呗,辅助树转来转去也是在id层面上转
看了看发现这个题要迅速找到某条边对应的管辖公司,给每条边一个id,简单一点就是。。(x-1)*8000+y
那看起来挺大的啊,map走起!
代码:
#include <map>
#include <cstdio>
#include <iostream>
using namespace std;
const int N=8005;const int C=105;
int ch[C][N][2],f[C][N],stack[N],du[C][N],deltaz[C][N];
map<int,int> mp;
int get(int id,int x){return ch[id][f[id][x]][1]==x;}
bool Is_root(int id,int x){return ch[id][f[id][x]][0]!=x && ch[id][f[id][x]][1]!=x;}
void pushdown(int id,int x)
{
if (deltaz[id][x])
{
swap(ch[id][x][0],ch[id][x][1]);
deltaz[id][ch[id][x][0]]^=1; deltaz[id][ch[id][x][1]]^=1;
deltaz[id][x]=0;
}
}
void rotate(int id,int x)
{
int old=f[id][x],oldf=f[id][old],which=get(id,x);bool gen=Is_root(id,old);
ch[id][old][which]=ch[id][x][which^1]; f[id][ch[id][x][which^1]]=old;
ch[id][x][which^1]=old; f[id][old]=x;
f[id][x]=oldf; if (!gen) ch[id][oldf][ch[id][oldf][1]==old]=x;
}
void splay(int id,int x)
{
int top=0,i;
for (i=x;!Is_root(id,i);i=f[id][i]) stack[++top]=i;
stack[++top]=i;
for (i=top;i>=1;i--) pushdown(id,stack[i]);
for (;!Is_root(id,x);rotate(id,x))
if (!Is_root(id,f[id][x])) rotate(id,get(id,f[id][x])==get(id,x)?f[id][x]:x);
}
void access(int id,int x)
{
int t=0;
for (;x;t=x,x=f[id][x])
{
splay(id,x);
ch[id][x][1]=t;
}
}
void reverse(int id,int x)
{
access(id,x);
splay(id,x);
deltaz[id][x]^=1;
}
int find(int id,int x)
{
while (ch[id][x][0]) x=ch[id][x][0];
return x;
}
bool connect(int id,int x,int y)
{
access(id,x); splay(id,x);
int fa1=find(id,x);
access(id,y); splay(id,y);
int fa2=find(id,y);
return fa1==fa2;
}
void Link(int id,int x,int y)
{
reverse(id,x);
f[id][x]=y;
splay(id,x);
du[id][x]++; du[id][y]++;
}
void Cut(int id,int x,int y)
{
reverse(id,x);
access(id,y);
splay(id,y);
ch[id][y][0]=f[id][x]=0;
du[id][x]--; du[id][y]--;
}
int main()
{
int n,m,c,T,i;
scanf("%d%d%d%d",&n,&m,&c,&T);
int x,y,z;
for (i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
mp[(x-1)*8000+y]=z; Link(z,x,y);
}
while (T--)
{
scanf("%d%d%d",&x,&y,&z);
int now=8000*(x-1)+y;
if (!mp[now]) printf("No such cable.\n");
else if (mp[now]==z) printf("Already owned.\n");
else if (du[z][x]==2 || du[z][y]==2) printf("Forbidden: monopoly.\n");
else if (connect(z,x,y)) printf("Forbidden: redundant.\n");
else
{
Cut(mp[now],x,y);
Link(z,x,y);
mp[now]=z;
printf("Sold.\n");
}
}
}