• BZOJ 4016 [FJOI2014]最短路径树问题 (贪心+点分治)


    题目大意:略 传送门

    硬是把两个题拼到了一起= =

    $dijkstra$搜出单源最短路,然后$dfs$建树,如果$dis_{v}=dis_{u}+e.val$,说明这条边在最短路图内,然后像$NOIP2018 D2T1$那样的思路,贪心地选出当前节点的所有子节点里,未被访问过的编号最小的节点递归,回溯后重复此过程。可以用$vector$预处理出来,或者用堆= =。

    然后就是很经典的点分治问题了

    求出树上固定边数的最长链,类似于[IOI2011]Race这道题的思路,只不过是反着搞。每次选择一个重心为根,开个桶统计答案就行了

    求固定长度链的个数。但这道题用桶可能会存不下,可以写$map$代替桶(不过数据里好像没有存不下的情况..)。

    由于判定条件是二元的,一个是边数一个是长度,排序双指针不知道行不行

    还有我把$vector$改成堆就过了是什么鬼

    代码巨长巨恶心

      1 #include <map>
      2 #include <queue>
      3 #include <vector>
      4 #include <cstdio>
      5 #include <cstring>
      6 #include <algorithm>
      7 #define N1 30010
      8 #define M1 1010
      9 #define ll long long
     10 #define inf 233333333
     11 #define it map<node,int>::iterator
     12 using namespace std;
     13 
     14 int gint()
     15 {
     16     int ret=0,fh=1;char c=getchar();
     17     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     18     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     19     return ret*fh;
     20 }
     21 int n,m,K;
     22 struct Edge{
     23 int to[N1<<2],nxt[N1<<2],val[N1<<2],head[N1],cte;
     24 void ae(int u,int v,int w)
     25 {
     26     cte++;to[cte]=v,val[cte]=w;
     27     nxt[cte]=head[u],head[u]=cte;
     28 }
     29 }g,e;
     30 namespace Build_Tree{
     31 struct node{
     32     int id,val;
     33     friend bool operator < (const node &s1,const node &s2){
     34         if(s1.val!=s2.val) return s1.val>s2.val;
     35         return s1.id>s2.id;
     36     }
     37 };
     38 int cmp(node s1,node s2){return s1.id<s2.id;}
     39 int vis[N1],dis[N1];
     40 void dijkstra()
     41 {
     42     memset(dis,0x3f,sizeof(dis));
     43     priority_queue<node>q;
     44     q.push((node){1,0}); dis[1]=0;
     45     int j,u,v; node k;
     46     while(!q.empty())
     47     {
     48         k=q.top(); q.pop(); u=k.id; if(vis[u]) continue; vis[u]=1;
     49         for(j=g.head[u];j;j=g.nxt[j])
     50         {
     51             v=g.to[j];
     52             if(dis[v]>dis[u]+g.val[j])
     53                 dis[v]=dis[u]+g.val[j], q.push((node){v,dis[v]});
     54         }
     55     }
     56     memset(vis,0,sizeof(vis));
     57 }
     58 priority_queue<node>q[N1];
     59 void dfs(int u)
     60 {
     61     vis[u]=1; node k;
     62     for(int j=g.head[u];j;j=g.nxt[j])
     63     {
     64         if(vis[g.to[j]]||dis[g.to[j]]!=dis[u]+g.val[j]) continue;
     65         q[u].push((node){g.val[j],g.to[j]});
     66     }
     67     while(!q[u].empty())
     68     {
     69         k=q[u].top(); q[u].pop(); if(vis[k.val]) continue;
     70         e.ae(u,k.val,k.id); e.ae(k.val,u,k.id);
     71         dfs(k.val);
     72     }
     73 }
     74 void Main()
     75 {
     76     dijkstra(); 
     77     dfs(1);
     78 }
     79 };
     80 int sz[N1],ms[N1],use[N1],tsz,G;
     81 void gra(int u,int dad)
     82 {
     83     sz[u]=1; ms[u]=0;
     84     for(int j=e.head[u];j;j=e.nxt[j])
     85     {
     86         if(use[e.to[j]]||e.to[j]==dad) continue;
     87         gra(e.to[j],u);
     88         sz[u]+=sz[e.to[j]]; ms[u]=max(ms[u],sz[e.to[j]]);
     89     }
     90     ms[u]=max(ms[u],tsz-sz[u]);
     91     if(ms[u]<ms[G]) G=u;
     92 }
     93 
     94 int ma[N1],q[N1],eq,tq[N1],et,dep[N1],dis[N1];
     95 
     96 namespace Find_ma{
     97 int ans;
     98 void dfs(int u,int dad)
     99 {
    100     if(dep[u]>K) return; tq[++et]=u;
    101     for(int j=e.head[u];j;j=e.nxt[j])
    102     {
    103         if(use[e.to[j]]||e.to[j]==dad) continue;
    104         dep[e.to[j]]=dep[u]+1; dis[e.to[j]]=dis[u]+e.val[j];
    105         dfs(e.to[j],u);
    106     }
    107 }
    108 void calc(int u)
    109 {
    110     int i,j,x;
    111     dep[u]=0; ma[0]=0;
    112     for(j=e.head[u];j;j=e.nxt[j])
    113     {
    114         if(use[e.to[j]]) continue;
    115         dep[e.to[j]]=1; dis[e.to[j]]=e.val[j];
    116         dfs(e.to[j],u);
    117         for(i=1;i<=et;i++)
    118         {
    119             x=tq[i];
    120             ans=max(ans,ma[K-dep[x]]+dis[x]);
    121         }
    122         while(et)
    123         {
    124             x=tq[et--]; q[++eq]=dep[x];
    125             ma[dep[x]]=max(ma[dep[x]],dis[x]);
    126         }
    127     }
    128     while(eq) ma[q[eq--]]=-inf; 
    129 }
    130 void main_dfs(int u)
    131 {
    132     int j,v; use[u]=1; calc(u);
    133     for(j=e.head[u];j;j=e.nxt[j])
    134     {
    135         v=e.to[j]; if(use[v]) continue;
    136         tsz=sz[v]; G=0; gra(v,u);
    137         main_dfs(G);
    138     }
    139 }
    140 void solve()
    141 {
    142     ms[0]=tsz=n; G=0; gra(1,-1); gra(G,-1);
    143     for(int i=1;i<=n;i++) ma[i]=-inf;
    144     main_dfs(G);
    145 }
    146 };
    147 
    148 namespace Count{
    149 
    150 struct node{
    151     int dis,dep;
    152     friend bool operator < (const node &s1,const node &s2)
    153     {
    154         if(s1.dis!=s2.dis) return s1.dis<s2.dis;
    155         return s1.dep<s2.dep;
    156     }
    157 };
    158 int M,ans; map<node,int>mp;
    159 void dfs(int u,int dad)
    160 {
    161     if(dis[u]>M||dep[u]>K) return;
    162     mp[(node){dis[u],dep[u]}]++;
    163     for(int j=e.head[u];j;j=e.nxt[j])
    164     {
    165         if(use[e.to[j]]||e.to[j]==dad) continue;
    166         dep[e.to[j]]=dep[u]+1; dis[e.to[j]]=dis[u]+e.val[j];
    167         dfs(e.to[j],u);
    168     }
    169 }
    170 int calc(int u)
    171 {
    172     int ret=0; node k,t; mp.clear(); dfs(u,-1);
    173     for(it i=mp.begin();i!=mp.end();i++)
    174     {
    175         k=i->first; t=(node){M-k.dis,K-k.dep};
    176         if(mp.find(t)==mp.end()) continue;
    177         if(k.dis==t.dis&&k.dep==t.dep) ret+=(i->second)*((i->second)-1);
    178         else ret+=mp[t]*(i->second);
    179     }
    180     return ret/2;
    181 }
    182 void main_dfs(int u)
    183 {
    184     int j,v; use[u]=1; dis[u]=0; dep[u]=0; ans+=calc(u);
    185     for(j=e.head[u];j;j=e.nxt[j])
    186     {
    187         v=e.to[j]; if(use[v]) continue;
    188         ans-=calc(v); tsz=sz[v]; G=0; gra(v,u);
    189         main_dfs(G);
    190     }
    191 }
    192 void solve()
    193 {
    194     M=Find_ma::ans;
    195     memset(use,0,sizeof(use));
    196     ms[0]=tsz=n; G=0; gra(1,-1); gra(G,-1);
    197     main_dfs(G);
    198 }
    199 };
    200 
    201 int main()
    202 {
    203     //freopen("t2.in","r",stdin);
    204     int i,x,y,z;
    205     scanf("%d%d%d",&n,&m,&K); K--;
    206     for(i=1;i<=m;i++)
    207     {
    208         x=gint(),y=gint(),z=gint();
    209         g.ae(x,y,z),g.ae(y,x,z);
    210     }
    211     Build_Tree::Main();
    212     Find_ma::solve(); 
    213     Count::solve();
    214     printf("%d %d
    ",Find_ma::ans,Count::ans);
    215     return 0;
    216 }
    217 /*
    218 6 6 4
    219 1 2 1
    220 2 3 1
    221 3 4 1
    222 2 5 1
    223 3 6 1
    224 5 6 1
    225 
    226 3 4
    227 
    228 7 6 4
    229 1 2 2
    230 1 3 1
    231 2 4 4
    232 2 5 3
    233 3 6 2
    234 5 7 2
    235 
    236 9 1
    237 */
  • 相关阅读:
    linux内核启动汇编部分详解
    linux内核zImage详解
    Linux内核zImage怎么来的?
    Linux内核编译make做了什么?
    关于makefile的几点经验
    note
    tmp0000
    tmp
    SSL学习与总结
    C++学习笔记
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10186939.html
Copyright © 2020-2023  润新知