zoukankan      html  css  js  c++  java
  • 洛谷 三月月赛 C

    呵呵呵呵,这个sb题做了好久,然并卵,还是不对。

    挖坑++

    然而我感觉我做的对了,偷瞄了一下题解应该没什么问题。

    这个题有n个点,n条边,所以是个基环树(我也不知道是不是这个名)

    要每个点有联通,就是一个n个点的环,要是答案最小,那么我们就要保留下一些最大的链

    现在我们考虑,因为一个点只有一个入度(n-1条边的话是一个严格从根节点单向向外的树),现在多了一个边,所以多了形成一个环

    那先现在这个东西(基环树)就是一个环外面挂着一些严格向外延展的子树。

    所以先考虑子树,对于每一个节点,贪心的保留一个权值最大的边连的儿子保留,其他的切掉(这里说的切掉是指重建),(这一步做完之后出来的东西就类似于树链剖分出来的重链)

    再来考虑环,与环相连的子树,选择切掉,那么环是不用动的,选择不切,那么在环上对应的下条边是要切掉的。(这里打一个标记,判断切没切,然后,没切的话要找环上最小的边切开)

    需要注意的是,可以不止一个基环树233333

      1 #include<bits/stdc++.h>
      2 #define N 100005
      3 #define LL long long
      4 #define inf 1LL<<60
      5 using namespace std;
      6 inline LL ra()
      7 {
      8     LL x=0,f=1; char ch=getchar();
      9     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
     10     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
     11     return x*f;
     12 }
     13 struct edge{
     14     int to,next; LL v;
     15 }e[N];
     16 int head[N],cnt,n,start,d[N];
     17 int top,ind,q[N],low[N],dfn[N],size[N],num,belong[N];
     18 LL ans,sum,f[N],del,cst[N];
     19 bool vis[N],cut,inq[N],can[N];
     20 void insert(int x, int y, LL v)
     21 {
     22     e[++cnt].next=head[x]; e[cnt].to=y; e[cnt].v=v; head[x]=cnt;
     23 }
     24 void tarjan(int x)
     25 {
     26     dfn[x]=low[x]=++ind;
     27     q[++top]=x; inq[x]=1;
     28     for (int i=head[x];i;i=e[i].next)
     29         if (!dfn[e[i].to])
     30         {
     31             tarjan(e[i].to);
     32             low[x]=min(low[e[i].to],low[x]);
     33         }
     34         else if (inq[e[i].to]) low[x]=min(low[x],dfn[e[i].to]);
     35     if (low[x]==dfn[x])
     36     {
     37         ++num;
     38         int now=-1;
     39         while (now!=x)
     40         {
     41             now=q[top--];
     42             belong[now]=num;
     43             size[num]++;
     44             inq[now]=0;
     45         }
     46     }
     47 }
     48 void get_cost(int x)
     49 {
     50     can[x]=1;
     51     for (int i=head[x];i;i=e[i].next)
     52     {
     53         if (vis[e[i].to]) cst[x]=e[i].v;
     54         if (e[i].to==start || !vis[e[i].to]) continue;
     55         get_cost(e[i].to);
     56     }
     57 }
     58 void solve_son(int x)
     59 {
     60     LL son_sum=0,son_mx=0;
     61     for (int i=head[x];i;i=e[i].next)
     62     {
     63         son_sum+=e[i].v,son_mx=max(son_mx,e[i].v);
     64         f[x]+=f[e[i].to];
     65         solve_son(e[i].to);
     66     }
     67     f[x]+=son_sum-son_mx;
     68 }
     69 void dfs(int x)
     70 {
     71     LL son_del=-inf; can[x]=1;
     72     for (int i=head[x];i;i=e[i].next)
     73     {
     74         son_del=max(son_del,-cst[x]);
     75         if (e[i].to==start) continue;
     76         if (vis[e[i].to]) dfs(e[i].to);
     77         else
     78         {
     79             solve_son(e[i].to);
     80             ans+=f[e[i].to]+e[i].v;
     81             son_del=max(son_del,e[i].v-cst[x]);
     82         }
     83     }
     84     if (son_del>0) cut=1,ans-=son_del; else del=max(del,son_del);
     85 }
     86 int main()
     87 {
     88     n=ra();
     89     for (int i=1; i<=n; i++) 
     90     {
     91         int x=ra();
     92         LL v=(LL)ra();
     93         if (x==i) ans+=v; else insert(x,i,v);
     94     }
     95     for (int i=1; i<=n; i++) 
     96         if (!dfn[i]) tarjan(i);
     97     int hehe=0;
     98     bool flag=0;
     99     for (int i=1; i<=n; i++)
    100         if (size[belong[i]]>1) 
    101         {
    102             if (hehe && hehe!=belong[i]) flag=1;
    103             hehe=belong[i];
    104             vis[i]=1;
    105         }
    106     for (int i=1; i<=n; i++)
    107         if (!vis[i]) {flag=1; break;}
    108     if (!flag)
    109     {
    110         cout<<"0"<<endl;
    111         return 0;
    112     }
    113     for (int i=1; i<=n; i++)
    114         if (vis[i] && !can[i])
    115         {
    116             start=i;
    117             get_cost(i);
    118         }
    119     memset(can,0,sizeof(can));
    120     for (int i=1; i<=n; i++)
    121         if (vis[i] && !can[i])
    122         {
    123             cut=0; del=-inf;
    124             start=i; dfs(i);
    125             if (!cut) ans-=del;
    126         }
    127 //    for (int i=1; i<=n; i++) printf("%d ",f[i]);
    128     cout<<ans<<endl;
    129     return 0;
    130 }
  • 相关阅读:
    WampServer Mysql配置
    Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
    Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
    Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 前10名
  • 原文地址:https://www.cnblogs.com/ccd2333/p/6545124.html
Copyright © 2011-2022 走看看