【GDOI2015】 水题 tarjan缩点

 

这一题,我当年只会$60$分做法。。。。。

我们考虑对原图跑一波边双,然后缩成一个森林。

对于森林中的每一棵树,我们钦定一个根。

令$siz[x]$表示以$x$为根的子树中,在原图中点的个数。

令当前的答案为$ans$

对于一条边$(u,v)$,如果这两个点在缩点后的同个点内,那么什么都不用管,直接输出$ans$即可。

否则我们先令$u=d[u]$,$v=d[v]$,其中$d[i]$表示原图中第$i$号点在缩点后的森林中的编号。

显然这两个点在同一棵树内,不妨设$dep[u]>dep[v]$,令$rt$表示$u$所在的树的根。

显然断掉这条边,增加的非联通点对个数为$siz[u]\times (siz[rt]-siz[u])$。

加上$ans$输出即可。

 

注意对1000取模!!!

 1 #include<bits/stdc++.h>
 2 #define L long long
 3 #define M 100005
 4 using namespace std;
 5 
 6 struct edge{int u,next;}e[M*22]={0}; int head[M]={0},head1[M]={0},use=0;
 7 void add(int x,int y){e[use].u=y;e[use].next=head[x];head[x]=use++;}
 8 void add1(int x,int y){use++;e[use].u=y;e[use].next=head1[x];head1[x]=use;}
 9 int dfn[M]={0},low[M]={0},b[M]={0},d[M]={0},siz[M]={0},cnt=0,t=0; stack<int> s;
10 int n,m,q;
11 void dfs(int x,int fa){
12     dfn[x]=low[x]=++t; s.push(x); b[x]=1;
13     for(int i=head[x];~i;i=e[i].next) 
14     if(i!=fa){
15         if(!dfn[e[i].u]) dfs(e[i].u,i^1),low[x]=min(low[x],low[e[i].u]);
16         else if(b[e[i].u]) low[x]=min(low[x],dfn[e[i].u]);
17     }
18     if(dfn[x]==low[x]){
19         cnt++; int u;
20         do{
21             u=s.top();s.pop();
22             b[x]=0; d[u]=cnt; siz[cnt]++;
23         }while(u!=x);
24     }
25 }
26 int du[M]={0},dep[M]={0},ff[M]={0};
27 void dfs1(int x,int fa){
28     dep[x]=dep[fa]+1; ff[x]=ff[fa];
29     for(int i=head1[x];i;i=e[i].next)
30     if(e[i].u!=fa) 
31     dfs1(e[i].u,x),siz[x]+=siz[e[i].u];
32 }
33 
34 int U[M*10]={0},V[M*10]={0};
35 int main(){
36     memset(head,-1,sizeof(head));
37     scanf("%d%d%d",&n,&m,&q);
38     for(int i=1;i<=m;i++){
39         int x,y; scanf("%d%d",&x,&y);
40         x++; y++; 
41         add(x,y); add(y,x);
42         U[i]=x; V[i]=y;
43     }
44     for(int i=1;i<=n;i++) if(!dfn[i])
45     dfs(i,-1);
46     for(int x=1;x<=n;x++)
47     for(int i=head[x];~i;i=e[i].next)
48     if(d[x]!=d[e[i].u]){
49         add1(d[x],d[e[i].u]); du[d[x]]++;
50     }
51     L ans=1LL*n*n;
52     for(int i=1;i<=cnt;i++)
53     if(du[i]==0||(du[i]==1&&dep[i]==0)){
54         ff[0]=i; dfs1(i,0);
55         ans-=1LL*siz[i]*siz[i];
56     }
57     ans/=2;
58     while(q--){
59         int id,x,y; scanf("%d",&id); id++;
60         x=U[id]; y=V[id];
61         x=d[x]; y=d[y];
62         if(x==y||ff[x]!=ff[y]){printf("%lld\n",ans%1000); continue;} 
63         if(dep[x]<dep[y]) swap(x,y);
64         L minus=1LL*siz[x]*(siz[ff[y]]-siz[x]);
65         printf("%lld\n",(ans+minus)%1000);
66     }
67 }
posted @ 2018-10-23 17:22  AlphaInf  阅读(296)  评论(0编辑  收藏  举报