zoukankan      html  css  js  c++  java
  • 【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] imes (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
    ",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
    ",(ans+minus)%1000);
    66     }
    67 }
  • 相关阅读:
    UVa 11384 Help is needed for Dexter (递归)
    HDU 4355 Party All the Time (三分求极值)
    UVa 11992 Fast Matrix Operations (线段树,区间修改)
    LA 3708 && POJ 3154 Graveyard (思维)
    LA 3942 && UVa 1401 Remember the Word (Trie + DP)
    LA 4329 Ping pong (树状数组)
    HDU 2058 The sum problem (数学+暴力)
    POJ 1458 Common Subsequence (DP+LCS,最长公共子序列)
    代理服务器
    .net垃圾回收
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/9837892.html
Copyright © 2011-2022 走看看