• loj2587 「APIO2018」铁人两项[圆方树+树形DP]


    主要卡在一个结论上。。关于点双有一个常用结论,也经常作为在圆方树/简单路径上的良好性质,对于任意点双内互不相同的三点$s,c,t$,都存在简单路径$s o c o t$,证明不会。可以参见clz博客。。我就是跟着他学的

    然后就好办了,转化为树上两点计经过点双内所有点个数,然后赋权后变为统计两两圆点对的路径权值和,这个就是一个树形DP,统计每个点作为圆点或者方点被所有路径经过多少次,加入答案。。

    还是比较裸的,因为重点还在于这个很多题都出现到的点双的简单路径的性质。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #define mst(x) memset(x,0,sizeof x)
     8 #define dbg(x) cerr << #x << " = " << x <<endl
     9 #define dbg2(x,y) cerr<< #x <<" = "<< x <<"  "<< #y <<" = "<< y <<endl
    10 using namespace std;
    11 typedef long long ll;
    12 typedef double db;
    13 typedef pair<int,int> pii;
    14 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    15 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    16 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    17 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    18 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    19 template<typename T>inline T read(T&x){
    20     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    21     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    22 }
    23 const int N=1e5+7;
    24 struct thxorz{
    25     int head[N<<1],nxt[N<<2],to[N<<2],tot;
    26     inline void add(int x,int y){
    27         to[++tot]=y,nxt[tot]=head[x],head[x]=tot;
    28         to[++tot]=x,nxt[tot]=head[y],head[y]=tot;
    29     }
    30 }G1,G2;
    31 int n,m;
    32 ll ans;
    33 int val[N<<1],siz[N<<1],cnt,Siz;
    34 int dfn[N],low[N],stk[N],top,tim;
    35 #define y G1.to[j]
    36 void tarjan(int x){
    37     dfn[x]=low[x]=++tim,stk[++top]=x,++Siz;
    38     for(register int j=G1.head[x];j;j=G1.nxt[j]){
    39         if(!dfn[y]){
    40             tarjan(y),MIN(low[x],low[y]);
    41             if(low[y]==dfn[x]){
    42                 int tmp,sum=0;++cnt;
    43                 do tmp=stk[top--],G2.add(cnt,tmp),val[tmp]=-1,++sum;while(tmp^y);
    44                 G2.add(cnt,x),val[x]=-1;val[cnt]=++sum;
    45             }
    46         }
    47         else MIN(low[x],dfn[y]);
    48     }
    49 }
    50 #undef y
    51 #define y G2.to[j]
    52 void dp(int x,int fa){
    53     int d=x<=n;siz[x]=d;
    54     for(register int j=G2.head[x];j;j=G2.nxt[j])if(y^fa){
    55         dp(y,x),siz[x]+=siz[y];
    56         ans+=siz[y]*1ll*(Siz-siz[y])*val[x];
    57     }
    58     ans+=d*(Siz-1)*1ll*val[x]+(Siz-siz[x])*1ll*siz[x]*val[x];
    59 }
    60 #undef y
    61 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
    62     read(n),read(m);cnt=n;
    63     for(register int i=1,x,y;i<=m;++i)read(x),read(y),G1.add(x,y);
    64     for(register int i=1;i<=n;++i)if(!dfn[i]){
    65         Siz=top=0;tarjan(i),dp(i,0);
    66     }
    67     printf("%lld
    ",ans);
    68     return 0;
    69 }
    View Code

    总结:图上简单路径题多半和点双有关系

  • 相关阅读:
    C#3.0之神奇的Lambda表达式和Lambda语句
    Expression Tree 学习笔记(一)
    C#对象序列化与反序列化
    Linux Shell编程入门
    ora-03113或者ora-12573 通信通道的文件结束出现异常错误:核心转储
    如何实现文档在线预览
    使用npoi导入Excel
    判断时间(时:分)是否在某个时间段内
    程序员开发时遇到的那些缩写和名词(记录)
    git
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11763062.html
Copyright © 2020-2023  润新知