zoukankan      html  css  js  c++  java
  • 习题:codevs 1519 过路费 解题报告

    今天拿了这道题目练练手,感觉自己代码能力又增强了不少;

    我的思路跟别人可能不一样。

    首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这个kruskal选边建图的过程。

     1 struct kruskalsolve{
     2     int l,r,w;
     3 }kr[maxm];
    此处省略的内容接下来会有给出全部代码
    4 int find(int x){ 5 if(f[x] != x)f[x] = find(f[x]); 6 return f[x]; 7 } 8 void kruskal_check(int m){ 9 int cnte = 0; 10 sort(kr+1,kr+m+1,cmp); 11 for(int i = 1;i <= n;++i){ 12 f[i] = i; 13 } 14 for(int i = 1;i <= m;++i){ 15 if(cnte == n-1)break; 16 int s = find(kr[i].l); 17 int t = find(kr[i].r); 18 if(s != t){ 19 f[s] = t; 20 e[++cnte][0] = kr[i].l; 21 e[cnte][1] = kr[i].r; 22 e[cnte][2] = kr[i].w; 23 addedge(kr[i].l,kr[i].r); 24 addedge(kr[i].r,kr[i].l); 25 } 26 } 27 }

    做到这里,有人可能觉得接下来一个LCA接着就可以AC了,不过蒟蒻认为这样做效率有点低,然后代码也不怎么好写,于是换成了树链剖分+线段树模板维护查询区间最大值的思路。(什么思路!!明明是套板子……这要解释的话就比较尴尬了)

    这样的话效率就是O(nlogn)的总效率,感觉不错,但是就是代码量稍微有点大,请读者见谅。

    建议大家还是先去学一下树链剖分的思路和板子,然后在看我的题解,毕竟光copy别人的,自己时间长了肯定忘,最好的还是自己懂了思路然后再自己手码出来。

    废话不说了,上代码

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <algorithm>
      6 using namespace std;
      7 const int maxn = 10005,maxm = 100005;
      8 int n,m,q,s,t;
      9 int id[maxn],top[maxn],son[maxn],fa[maxn],h[maxn],cnt,siz[maxn],dep[maxn],val[maxn],num,f[maxn];
     10 struct kruskalsolve{
     11     int l,r,w;
     12 }kr[maxm];
     13 struct edge{
     14     int fr,to,next;
     15 }edges[maxn<<1];
     16 struct segtree{
     17     int l,r,val;
     18 }tr[maxm<<1];
     19 int e[maxn][3];
     20 bool cmp(kruskalsolve a,kruskalsolve b){
     21     return a.w < b.w;
     22 }
     23 void init(){
     24     cnt = 0;
     25     memset(h,-1,sizeof(h));
     26     memset(dep,0,sizeof(dep));
     27     memset(siz,0,sizeof(siz));
     28     memset(fa,0,sizeof(fa));
     29     memset(id,0,sizeof(id));
     30     memset(edges,0,sizeof(edge));
     31     memset(val,0,sizeof(val));
     32     memset(e,0,sizeof(e));
     33     memset(top,0,sizeof(top));
     34     memset(tr,0,sizeof(tr));
     35     num = 0;
     36 }
     37 void addedge(int u,int v){
     38     edges[cnt].fr = u;edges[cnt].to = v;edges[cnt].next = h[u];
     39     h[u] = cnt++;
     40 }
     41 int find(int x){
     42     if(f[x] != x)f[x] = find(f[x]);
     43     return f[x];
     44 }
     45 void kruskal_check(int m){
     46     int cnte = 0;
     47     sort(kr+1,kr+m+1,cmp);
     48     for(int i = 1;i <= n;++i){
     49         f[i] = i;
     50     }
     51     for(int i = 1;i <= m;++i){
     52         if(cnte == n-1)break;
     53         int s = find(kr[i].l);
     54         int t = find(kr[i].r);
     55         if(s != t){
     56             f[s] = t;
     57             e[++cnte][0] = kr[i].l;
     58             e[cnte][1] = kr[i].r;
     59             e[cnte][2] = kr[i].w;
     60             addedge(kr[i].l,kr[i].r);
     61             addedge(kr[i].r,kr[i].l);
     62         }
     63     }
     64 }
     65 void dfs1(int now ,int father ,int d){
     66     dep[now] = d;
     67     fa[now] = father;
     68     son[now] = 0;
     69     siz[now] = 1;
     70     for(int i = h[now];i != -1;i = edges[i].next){
     71         edge e1 = edges[i];
     72         if(e1.to == father)continue;
     73         dfs1(e1.to,now,d+1);
     74         siz[now] += siz[e1.to];
     75         if(siz[son[now]] < siz[e1.to])son[now] = e1.to;
     76     }
     77 }
     78 void getpos(int now,int tp){
     79     id[now] = ++num;
     80     top[now] = tp;
     81     if(son[now])getpos(son[now],tp);
     82     for(int i = h[now];i != -1;i = edges[i].next){
     83         edge e1 = edges[i];
     84         if(e1.to == son[now] || e1.to == fa[now])continue;
     85         getpos(e1.to,e1.to);
     86     }
     87 }
     88 void push_up(int v){
     89     tr[v].val = max(tr[v<<1].val,tr[v<<1|1].val);
     90 }
     91 void build(int l,int r,int now){
     92     tr[now].l = l;
     93     tr[now].r = r;
     94     if(l == r){
     95         tr[now].val = val[l];
     96         return;
     97     }
     98     int mid = (l + r) >> 1;
     99     build(l,mid,now<<1);
    100     build(mid+1,r,now<<1|1);
    101     push_up(now);
    102 }
    103 int query(int x,int l,int r){
    104     if(l <= tr[x].l && r >= tr[x].r){
    105         return tr[x].val;
    106     }
    107     int ans = 0;
    108     int mid = (tr[x].l + tr[x].r) >> 1;
    109     if(l <= mid)ans = max(ans,query(x<<1,l,r));
    110     if(r > mid)ans = max(ans,query(x<<1|1,l,r));
    111     return ans;
    112 }
    113 int youth(int u,int v){
    114     int ans = 0;
    115     while(top[u] != top[v]){
    116         if(dep[top[u]] < dep[top[v]])swap(u,v);
    117         ans = max(ans,query(1,id[top[u]],id[u]));
    118         u = fa[top[u]];
    119     }
    120     if(u == v)return ans;
    121     if(dep[u] > dep[v])swap(u,v);
    122     ans = max(ans,query(1,id[son[u]],id[v]));
    123     return ans;
    124 }
    125 int main(){
    126     init();
    127     scanf("%d%d",&n,&m);
    128     for(int i = 1;i <= m;++i){
    129         scanf("%d%d%d",&kr[i].l,&kr[i].r,&kr[i].w);
    130     }
    131     kruskal_check(m);
    132     dfs1(1,-1,1);
    133     getpos(1,1);
    134     for(int i = 1;i < n;++i){
    135         if(dep[e[i][0]] < dep[e[i][1]])swap(e[i][0],e[i][1]);
    136         val[id[e[i][0]]] = e[i][2];
    137     }
    138     build(1,n,1);
    139     scanf("%d",&q);
    140     for(int i = 1;i <= q;++i){
    141         scanf("%d%d",&s,&t);
    142         printf("%d
    ",youth(s,t));
    143     }
    144     return 0;
    145 }

    这次写的解题报告就到这里吧,以后会尽量去写。

  • 相关阅读:
    [Linux] Ubuntu Server 12.04 LTS 平台上搭建WordPress(Nginx+MySQL+PHP) Part IV
    [Linux] Ubuntu Server 12.04 LTS 平台上搭建WordPress(Nginx+MySQL+PHP) Part III
    [Linux] Ubuntu Server 12.04 LTS 平台上搭建WordPress(Nginx+MySql+PHP) Part II
    [Linux] Ubuntu Server 12.04 LTS 平台上搭建WordPress(Nginx+MySql+PHP) Part I
    [C#] Extension Method 扩展方法
    [IIS] eset/Restart/Recycling/Refresh 的区别
    CSOM:服务器不允许将邮件大于 2097152 字节
    6条可以成为更好程序员的建议
    2019 就要到了,拥抱 Or 抛弃 sharepoint 开发?
    解耦UI层-可维护的Javascript 编写指南
  • 原文地址:https://www.cnblogs.com/gangding/p/5539648.html
Copyright © 2011-2022 走看看