枚举重点问题:找枚举点(特殊,代表一类)
图 枚举 边或点(讲解中枚举了边) 枚边则枚BD
60算法
关于B点枚举相连边记为x条 关于D点枚举相连边记为y条 BD总的y型有(x个数里选2个的组合数)*y 解决第一问
求长度max:枚举时记录B点的最大次大和D点的最大 相加
100算法
因为n200000,时间复杂度最大O(N)或O(NlogN)
只能枚举一次 输入时预处理
开数组 记每个点连的边的个数 记每个点的最大边 次大边 和 emmm 次次大边
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long n,x,y,z,ans1,cnt,max1;
struct Edge
{
long long to,nexty,dis;
}edge[400005];
long long head[400000];
long long mx[400003][3];
long long b[400003];
void add(long u,long v,long l)
{
cnt++;
edge[cnt].to=v;
edge[cnt].nexty=head[u];
edge[cnt].dis=l;
head[u]=cnt;
}
long long c(long long x)
{
return x*(x-1)/2;
}
long long lng(long long x,long long y,long long l)
{
long long ss=0;
if(l==mx[x][0]) ss=ss+mx[x][1]+mx[x][2];
else if(l==mx[x][1]) ss=ss+mx[x][0]+mx[x][2];
else ss=ss+mx[x][0]+mx[x][1];
if(l==mx[y][0]) ss=ss+mx[y][1];
else ss=ss+mx[y][0];
return ss+l;
}
void mxx(long long x,long long z)
{
if(z>mx[x][0]){
mx[x][2]=mx[x][1];
mx[x][1]=mx[x][0];
mx[x][0]=z;
return ;
}
if(z>mx[x][1]){
mx[x][2]=mx[x][1];
mx[x][1]=z;
return ;
}
if(z>mx[x][2]){
mx[x][2]=z;
return ;
}
}
int main()
{
freopen("question.in","r",stdin);
freopen("question.out","w",stdout);
long long i,j,jj,ll,mm;
scanf("%d",&n);
for(i=1;i<=n-1;i++) {
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
b[x]++;
add(y,x,z);
b[y]++;
mxx(x,z);
mxx(y,z);
}
for(i=1;i<=n;i++)
{
if(b[i]>=3)
for(j=head[i];j;j=edge[j].nexty)
{
jj=edge[j].to;
ll=edge[j].dis;
if(b[jj]>=2)
{
ans1+=c(b[i]-1)*(b[jj]-1);
mm=lng(i,jj,ll);
if(mm>max1) max1=mm;
}
}
}
cout<<ans1<<endl<<max1;
fclose(stdin);
fclose(stdout);
return 0;
}
亮点 卡常cin超时两个点
枚举思想