Problem C: 星球联盟
Time Limit: 4 Sec Memory Limit: 256 MBSubmit: 58 Solved: 16
[ Submit][ Status][ Web Board]
Description
在遥远的S星系中一共有N个星球,编号为1…N。其中的一些星球决定组成联盟,以方便相互间的交流。但是,组成
联盟的首要条件就是交通条件。初始时,在这N个星球间有M条太空隧道。每条太空隧道连接两个星球,使得它们能
够相互到达。若两个星球属于同一个联盟,则必须存在一条环形线路经过这两个星球,即两个星球间存在两条没有
公共隧道的路径。为了壮大联盟的队伍,这些星球将建设P条新的太空隧道。这P条新隧道将按顺序依次建成。一条
新轨道建成后,可能会使一些星球属于同一个联盟。你的任务是计算出,在一条新隧道建设完毕后,判断这条新轨
道连接的两个星球是否属于同一个联盟,如果属于同一个联盟就计算出这个联盟中有多少个星球。
联盟的首要条件就是交通条件。初始时,在这N个星球间有M条太空隧道。每条太空隧道连接两个星球,使得它们能
够相互到达。若两个星球属于同一个联盟,则必须存在一条环形线路经过这两个星球,即两个星球间存在两条没有
公共隧道的路径。为了壮大联盟的队伍,这些星球将建设P条新的太空隧道。这P条新隧道将按顺序依次建成。一条
新轨道建成后,可能会使一些星球属于同一个联盟。你的任务是计算出,在一条新隧道建设完毕后,判断这条新轨
道连接的两个星球是否属于同一个联盟,如果属于同一个联盟就计算出这个联盟中有多少个星球。
Input
第1行三个整数N,M和P,分别表示总星球数,初始时太空隧道的数目和即将建设的轨道数目。
第2至第M+1行,每行两个整数,表示初始时的每条太空隧道连接的两个星球编号。
第M+2行至第M+P+1行,每行两个整数,表示新建的太空隧道连接的两个星球编号。
这些太空隧道按照输入的顺序依次建成。
对于10%的数据有1≤N,M,P≤100;
对于40%的数据有1≤N,M,P≤2000;
对于100%的数据有1≤N,M,P≤200000。
第2至第M+1行,每行两个整数,表示初始时的每条太空隧道连接的两个星球编号。
第M+2行至第M+P+1行,每行两个整数,表示新建的太空隧道连接的两个星球编号。
这些太空隧道按照输入的顺序依次建成。
对于10%的数据有1≤N,M,P≤100;
对于40%的数据有1≤N,M,P≤2000;
对于100%的数据有1≤N,M,P≤200000。
Output
输出共P行。如果这条新的太空隧道连接的两个星球属于同一个联盟,就输出一个整数,表示这两个星球所在联盟
的星球数。如果这条新的太空隧道连接的两个星球不属于同一个联盟,就输出"No"(不含引号)。
的星球数。如果这条新的太空隧道连接的两个星球不属于同一个联盟,就输出"No"(不含引号)。
Sample Input
3 2 1
1 2
1 3
2 3
Sample Output
3
【样例1说明】
新建成的隧道连接2、3两个星球。
这条隧道1和2,2和3,1和3之间都存在环形线路。1,2,3同属一个联盟,答案为3
HINT
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#define N 4000003
using namespace std;
int n,m,k,belong[N],deep[N];
int fa[N],point[N],nxt[N],v[N],top[N],size[N],tot,cnt;
struct data
{
int x,y,opt,ans;
}a[N],b[N];
void add(int x,int y)
{
tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
//cout<<x<<" "<<y<<endl;
}
int find(int x)
{
if (fa[x]==x) return x;
fa[x]=find(fa[x]);
return fa[x];
}
void dfs(int x,int f)
{
belong[x]=f; deep[x]=deep[f]+1;
for (int i=point[x];i;i=nxt[i])
if (v[i]!=f)
dfs(v[i],x);
}
int lca(int x,int y)
{
x=find(x); y=find(y);
if (deep[x]<deep[y]) swap(x,y);
while (find(x)!=find(y))
{
int nowx=find(x);
int nowy=find(belong[nowx]);
if (nowy!=nowx)
size[nowy]+=size[nowx],fa[nowx]=nowy;
x=nowy;
if(deep[x]<deep[y]) swap(x,y);
}
return find(x);
}
int main()
{
freopen("a.in","r",stdin);
freopen("my.out","w",stdout);
scanf("%d%d%d",&k,&n,&m);
for (int i=1;i<=k;i++) fa[i]=i;
for (int i=1;i<=n;i++)
{
int x,y; scanf("%d%d",&x,&y);
int r1=find(x); int r2=find(y);
if (r1!=r2)
fa[r2]=r1,add(x,y);
else
b[++cnt].x=x,b[cnt].y=y;
}
for (int i=1;i<=m;i++)
{
int x,y; scanf("%d%d",&x,&y);
int r1=find(x); int r2=find(y);
if (r1!=r2)
{
fa[r2]=r1; add(x,y);
a[i].opt=1;
}
a[i].x=x; a[i].y=y;
}
for (int i=1;i<=k;i++)
{
int r1=find(1);
int r2=find(i);
if (r1!=r2)
{
fa[r2]=r1;
add(1,i);
}
}
dfs(1,0);
for (int i=1;i<=k;i++)
fa[i]=i,size[i]=1;
for (int i=1;i<=cnt;i++)
lca(b[i].x,b[i].y);
for (int i=1;i<=m;i++)
if (a[i].opt!=1)
{
int t=lca(a[i].x,a[i].y);
a[i].ans=size[t];
}
for (int i=1;i<=m;i++)
if (a[i].opt==1)
printf("No\n");
else printf("%d\n",a[i].ans);
}