[JSOI2017]原力

题目大意:
  一个$n(n\le5\times10^4)$个点,$m(m\le10^5)$条边的无向图。每条边有一个边权$w_i(w_i\le10^6)$和一个附加属性$t_i(t_i\in\{R,G,B\})$。定义一个三元环的价值为个条边权值之积,求所有满足每条边附加属性互不相同的三元环的价值和。

思路:
  对结点按照度数分为两组分块,度数$\ge\sqrt m$的算作重点,否则算轻点。对于三元环三个顶点都是重点的情况,直接暴力即可,复杂度$O(m\sqrt m)$。对于含有轻点的三元环,$O(m)$枚举第一个点及一条出边,$O(\sqrt m)$枚举第二条出边,复杂度还是$O(m\sqrt m)$。这里对于边权的查询应该是利用哈希实现的,但是用map也能过,复杂度$O(m\sqrt m\log m)$。

 1 #include<map>
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<cctype>
 5 #include<cstring>
 6 typedef long long int64;
 7 inline int getint() {
 8     register char ch;
 9     while(!isdigit(ch=getchar()));
10     register int x=ch^'0';
11     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
12     return x;
13 }
14 inline int gettype() {
15     register char ch;
16     while(!isalpha(ch=getchar()));
17     return ch!='R'?ch!='G'?0:1:2;
18 }
19 const int N=5e4+1,M=2e5,mod=1e9+7;
20 struct Edge {
21     int to,w,type,next;
22 };
23 Edge e[M];
24 int h[N],sz,deg[N],c[N];
25 struct Node {
26     int u,v,type;
27     bool operator < (const Node &another) const {
28         if(u!=another.u) return u<another.u;
29         if(v!=another.v) return v<another.v;
30         return type<another.type;
31     }
32 };
33 std::map<Node,int> map;
34 inline void add_edge(const int &u,const int &v,const int &w,const int &t) {
35     e[sz]=(Edge){v,w,t,h[u]};h[u]=sz++;deg[u]++;
36     (map[(Node){u,v,t}]+=w)%=mod;
37 }
38 int main() {
39     memset(h,-1,sizeof h);
40     const int n=getint(),m=getint(),block=sqrt(m);
41     for(register int i=0;i<m;i++) {
42         const int u=getint(),v=getint(),w=getint(),t=gettype();
43         add_edge(u,v,w,t);
44         add_edge(v,u,w,t);
45     }
46     for(register int i=1;i<=n;i++) {
47         if(deg[i]>=block) c[++c[0]]=i;
48     }
49     int ans=0;
50     for(register int i=1;i<=c[0];i++) {
51         for(register int j=1;j<=c[0];j++) {
52             for(register int k=1;k<=c[0];k++) {
53                 (ans+=(int64)map[(Node){c[i],c[j],0}]*map[(Node){c[j],c[k],1}]%mod*map[(Node){c[k],c[i],2}]%mod)%=mod;
54             }
55         }
56     }
57     for(register int i=1;i<=n;i++) {
58         if(deg[i]>=block) continue;
59         for(register int j=h[i];~j;j=e[j].next) {
60             if(deg[e[j].to]<block&&e[j].to<=i) continue;
61             for(register int k=e[j].next;~k;k=e[k].next) {
62                 if(e[j].type==e[k].type||(deg[e[k].to]<block&&e[k].to<=i)) continue;
63                 (ans+=(int64)map[(Node){e[j].to,e[k].to,3-e[j].type-e[k].type}]*e[j].w%mod*e[k].w%mod)%=mod;
64             }
65         }
66     }
67     printf("%d\n",ans);
68     return 0;
69 }

 

posted @ 2018-04-02 15:42  skylee03  阅读(151)  评论(0编辑  收藏  举报