RP路

RP

题目描述

XRP十分有研究,现在他向你提出了一个问题。给出一棵N个节点的树,有些边是RP边,至少经过一条RP边的路径定义为RP路,其他路径定义为非RP路。现在,你需要令最多一条RP边变为非RP边,使得RP路的数量最少。
数据范围

测试点 N
1~2 ≤100
3~5 ≤5 000
6 ≤10 000
7~10 ≤100 000

输入格式 2074.in

第一行一个正整数N

接下来N-1行,每行三个整数A,B,C。表示节点A,B间存在一条边,如果是RP边,那么C=1,否则C=0。节点从1开始到N标号。

输出格式 2074.out

一个表示你的答案的整数。

输入样例 2074.in

5
3 5 1
1 4 1
5 2 1
2 1 0

输出样例 2074.out

7

       这题,涉及到一种转化思想。基本思路如下:我们直接求RP路径有多少条,不太好求,直接求是N*N的。那就将其转化成总路径条数减去非RP路径条数,这就是初始RP路径条数。然后,分别计算,去掉每条RP边,会减少的RP路径条数。初始RP路径条数减去这其中的最大值即为所求。

   总路径条数?自然是N*(N-1)/2。

   那么,非RP路径如何求?根据定义,非RP路径中的所有边皆为非RP边,其中不能有RP边。通过手动画RP树可以发现,可以将原图进行“缩点”,缩成以RP路为树边,以非RP子集为结点的树。(缩点可用并查集/DFS)。所有新点内部的路径数之和即为非RP路径总数。

   去掉每条RP边,会减少的RP路径条数如何求?明确一点:会被减少的RP路径,路径中有且只有一条RP边,就是被删的那条。因此不难发现,会减少的RP路径条数,等于此RP边所连接的两非RP子集的结点乘积。

   至此,题目所求可以求出。

   说白了,此题我没有想出的原因,就是没有想到这样“缩点”。因此,观察特征,总结潜在规律,打开思路解题很重要。。。。造化不够。。。。。……

   代码如下:

#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
using namespacestd;
const intMAXN=1e5+5;
struct poi
{
       int to,type;
};
vector
      
      
       
       edge[MAXN];
long longn,a,b,c,f[MAXN],v[MAXN],father[MAXN],vi[MAXN];
long longans,minu;
int findA(int x)
{
       if(father[x]==x)      return x;
       return father[x]=findA(father[x]);
}
void init(inta,int b,int c)
{
       edge[a].push_back((poi){b,c});
       edge[b].push_back((poi){a,c});
       if(c==0)
       {
              int root1=findA(a),root2=findA(b);
              father[root1]=root2;
       }
}
void dfs(intnow)
{
       vi[now]=1;
       int size=edge[now].size();
       for(int i=0;i
       
       
         >n; for(int i=1;i<=n;i++) father[i]=i; for(int i=1;i 
        
          >a>>b>>c; init(a,b,c); } for(int i=1;i<=n;i++) { int root=findA(i); father[i]=root; v[father[i]]++; } ans=n*(n-1)/2; for(int i=1;i<=n;i++) ans-=v[i]*(v[i]-1)/2; minu=0; dfs(1); cout< 
         
           < 
           
          
         
       
      
      
     
     
    
    
   
   


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值