题意
一个原力网络可以看成是一个可能存在重边但没有自环的无向图。每条边有一种属性和一个权值。属性可能是R、G
、B三种当中的一种,代表这条边上原力的类型。权值是一个正整数,代表这条边上的原力强度。原力技术的核心
在于将R、G、B三种不同的原力融合在一起产生单一的、便于利用的原力。为了评估一个能源网络,JYY需要找到所
有满足要求的三元环(首尾相接的三条边),其中R、G、B三种边各一条。一个三元环产生的能量是其中三条边的
权值之积。
现在对于给出的原力网络,JYY想知道这个网络的总能量是多少。网络的总能量是所有满足要求三元环的能量之和。
前言
我写hash,这次居然忘记处理冲突了。。
WA了好几发QAQ
我真是SB了
题解
套路地
把度数比
m−−√
m
大的标为大点,否则标为小点
容易知道,大点之后
m−−√
m
个
考虑三元组三个都是大点,直接暴力枚举就可以了,
m−−√3
m
3
否则枚举一个小点,枚举它的两条边
考虑每一条边被枚举多少次,就是
m−−√
m
次
因为他一端的小点,只有
m−−√
m
个出度
于是就可以通过了
剩下的hash解决即可
CODE:
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long LL;
const LL MOD=1e9+7;
const LL N=50005;
const LL M=100005;
const LL MOD1=1000037;
LL sum[MOD1][3];
LL X[MOD1],Y[MOD1];
LL n,m;
LL get (LL x,LL y)
{if (x>y) swap(x,y);
LL now=(x*2333+y*23333)%MOD1;
while(X[now]!=0)
{
if (X[now]==x&&Y[now]==y) break;
if(now==MOD1-1)now=0;
else now++;
}
return now;
}
LL d[N];
vector<LL> a,b;
struct qq
{
LL x,y,last;
}e[M*2];LL num,last[N];
void init (LL x,LL y)
{
num++;
e[num].x=x;e[num].y=y;
e[num].last=last[x];
last[x]=num;
}
bool ok[N];//这个点是不是大点
LL calc (LL x,LL y,LL z)
{
LL lalal=0;
lalal=lalal+sum[x][0]*sum[y][1]%MOD*sum[z][2]%MOD;
lalal=lalal+sum[x][0]*sum[y][2]%MOD*sum[z][1]%MOD;
lalal=lalal+sum[x][1]*sum[y][0]%MOD*sum[z][2]%MOD;
lalal=lalal+sum[x][1]*sum[y][2]%MOD*sum[z][0]%MOD;
lalal=lalal+sum[x][2]*sum[y][0]%MOD*sum[z][1]%MOD;
lalal=lalal+sum[x][2]*sum[y][1]%MOD*sum[z][0]%MOD;
return lalal%MOD;
}
int main()
{
num=0;memset(last,-1,sizeof(last));
scanf("%lld%lld",&n,&m);
LL size=sqrt(m)+1;
for (LL u=1;u<=m;u++)
{
LL x,y,w;
scanf("%lld%lld%lld",&x,&y,&w);
if (x>y) swap(x,y);
LL t=get(x,y);
// printf("%lld %lld %lld\n",x,y,t);
if (X[t]==0)
{
X[t]=x;Y[t]=y;
init(x,y);init(y,x);
d[x]++;d[y]++;
}
char ch=getchar();
while (ch!='R'&&ch!='G'&&ch!='B') ch=getchar();
if (ch=='R') sum[t][0]+=w;
if (ch=='G') sum[t][1]+=w;
if (ch=='B') sum[t][2]+=w;
sum[t][0]%=MOD;sum[t][1]%=MOD;sum[t][2]%=MOD;
}
for (LL u=1;u<=n;u++)
{
if (d[u]>=size)
{
// printf("YES:%lld\n",u);
ok[u]=true;
a.push_back(u);
}
else
{
ok[u]=false;
b.push_back(u);
}
}
LL tot=a.size();
LL ans=0;
for (LL u=0;u<tot;u++)
for (LL i=u+1;i<tot;i++)
{
LL t1=get(a[u],a[i]);
for (LL j=i+1;j<tot;j++)
{
LL t2=get(a[u],a[j]),t3=get(a[i],a[j]);
ans=(ans+calc(t1,t2,t3))%MOD;
}
}
tot=b.size();
for (LL u=0;u<tot;u++)//枚举所有小点
{
LL x=b[u];
for (LL i=last[x];i!=-1;i=e[i].last)
{
for (LL j=last[x];j!=-1;j=e[j].last)
{
LL y1=e[i].y,y2=e[j].y;
if (ok[y1]==false&&ok[y2]==false)
{
if (x<y1&&y1<y2)
{// printf("A:%lld %lld %lld\n",x,y1,y2);
ans=(ans+calc(get(x,y1),get(y1,y2),get(x,y2)))%MOD;
}
}
else if (ok[y1]==false)
{
if (x<y1)
{
// printf("B:%lld %lld %lld %lld\n",x,y1,y2,calc(get(x,y1),get(y1,y2),get(x,y2)));
ans=(ans+calc(get(x,y1),get(y1,y2),get(x,y2)))%MOD;
}
}
else if (y1<y2&&ok[y1]&&ok[y2])
ans=(ans+calc(get(x,y1),get(y1,y2),get(x,y2)))%MOD;
}
}
}
printf("%lld\n",ans);
return 0;
}