概述
题目链接:http://uoj.ac/problem/14
【分析】
先请允许我诚意地orz DZY神犇...
UOJ的题解真的很良心...http://vfleaking.blog.uoj.ac/blog/15
主要内容就是一个按秩合并的并查集,支持删边加边。在没有Return操作的情况下,这么做是nlogn的,已经足够了,但是有Return操作,在删完大量的边后重新加边会使时间复杂度变成n^2。
这时考虑离线处理,在进行Delete操作之前看看下一个操作是不是Return,如果不是就删边,如果是就不要删边,事先用一个数组Res[i]记录一下图中边数为i时最小生成树的大小,本次Delete操作的结果就是Res[当前图中边数-删去的边数]。
【代码】
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn=500010;
char cor[maxn][10];
int corx[maxn],cory[maxn];
int size[maxn],f[maxn],Ef[maxn];
int Q[maxn],tail;
LL Res[maxn];
int n,m;
void Init()
{
scanf("%d%d",&n,&m);
int x,y;
for (int i=1;i<=m;i++)
{
scanf("%s",cor[i]);
if (cor[i][0]=='A') scanf("%d%d",&corx[i],&cory[i]);
else if (cor[i][0]=='D') scanf("%d",&corx[i]);
}
}
int Find(int x) {return (f[x]==x)?x:Find(f[x]);}
void Add_Edge(int x,int y,int d)
{
int px=Find(x),py=Find(y);
Q[tail++]=d;
if (px==py) {Ef[d]=-1;return;}
if (size[px]>size[py]) swap(px,py);
f[px]=py;
for (int i=py;;py=f[py])
{
size[py]+=size[px];
if (f[py]==py) break;
}
Ef[d]=px;
}
void Delete(int p)
{
for (int px=f[p];;px=f[px])
{
size[px]-=size[p];
if (f[px]==px) break;
}
f[p]=p;
}
void Solve()
{
int tot=0,trcnt=0;
LL ans=0;
for (int i=1;i<=n;i++) f[i]=i,size[i]=1;
for (int i=1;i<=m;i++)
if (cor[i][0]=='A')
{
Add_Edge(corx[i],cory[i],i);
if (Ef[i]!=-1) ans+=i,trcnt++;
Res[++tot]=(trcnt<n-1)?0:ans;
printf("%lldn",Res[tot]);
if (cor[i+1][0]=='R') cor[i+1][0]='D',corx[i+1]=1;
}
else if (cor[i][0]=='D')
{
if (cor[i+1][0]=='R') {printf("%lldn%lldn",Res[tot-corx[i]],Res[tot]);continue;}
while (corx[i]--)
{
int p=Q[--tail];tot--;
if (Ef[p]==-1) continue;
Delete(Ef[p]);
ans-=p;trcnt--;
}
Res[tot]=(trcnt<n-1)?0:ans;
printf("%lldn",Res[tot]);
}
}
int main()
{
Init();
Solve();
return 0;
}
最后
以上就是欢喜火龙果为你收集整理的UOJ#14【UER#1】DZY Loves Graph的全部内容,希望文章能够帮你解决UOJ#14【UER#1】DZY Loves Graph所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复