2012ACM成都赛区现场赛D hdu4467 Graph
在现场的时候想出了算法,可惜一直tle,结束后才想到是被重边给卡了。。。。。。
我想到的算法思路如下:
对于一个单图,一个点的相邻点中度数比它大的点的数目不会超过(2m)^(1/2)个,所以对每个点分别纪录两种颜色的比它度数小的邻点到它的边权总和,再维护所有边中颜色为00,11,01/10的边权总和。这样遇到查询操作则直接输出结果,遇到改色操作则先用此点纪录的度数比它小的邻点信息修改总值,再逐边维护度数比它大的邻点的纪录值和总值,此项的时间复杂度是O(m^1/2)。总时间复杂度是O(q*m^1/2);
由于m<=100000,q<=100000,所以此算法可过。
现场太悲剧了,完全没注意到重边的问题,当时三个人各调一题,没人帮忙,结果就卡到结束。。
#include <stdio.h> #include "stdlib.h" long long w[110000][2],d[110000],ed[110000][3],tot[3],col[110000],edg[110000]; int comp(const void *a,const void *b){ long long t; t=((long long *)a)[0]-((long long *)b)[0]; if (t>0){ return 1; } else { if (t<0){ return -1; } else { return 0; } } } int main(){ long long n,m,i,j,k,t,test,q,x,y; char s[100]; test=0; while (scanf("%I64d%I64d",&n,&m)!=EOF){ test++; for (i=1;i<=n;i++){ scanf("%I64d",col+i); } for (i=0;i<m;i++){ scanf("%I64d%I64d%I64d",ed[i],ed[i]+1,ed[i]+2); if (ed[i][0]>ed[i][1]){ t=ed[i][0]; ed[i][0]=ed[i][1]; ed[i][1]=t; } } qsort(ed,m,sizeof(long long )*3,comp); for (i=1,k=0;i<m;i++){ if (ed[i][0]==ed[i-1][0]&&ed[i][1]==ed[i-1][1]){ k++; ed[i-k][2]+=ed[i][2]; } else { ed[i-k][0]=ed[i][0]; ed[i-k][1]=ed[i][1]; ed[i-k][2]=ed[i][2]; } } m-=k; for (i=1;i<=n;i++){ d[i]=0; w[i][0]=0; w[i][1]=0; } for (i=0;i<m;i++){ d[ed[i][0]]++; d[ed[i][1]]++; } for (i=0;i<m;i++){ if (d[ed[i][0]]>d[ed[i][1]]){ t=ed[i][0]; ed[i][0]=ed[i][1]; ed[i][1]=t; } } qsort(ed, m, sizeof(long long )*3,comp); ed[m][0]=n+1; for (i=1,j=0;i<=n;i++){ edg[i]=j; while (ed[j][0]==i){ j++; } } edg[n+1]=m; tot[0]=0; tot[1]=0; tot[2]=0; for (i=0;i<m;i++){ if (col[ed[i][0]]!=col[ed[i][1]]){ tot[2]+=ed[i][2]; } else { tot[col[ed[i][0]]]+=ed[i][2]; } w[ed[i][1]][col[ed[i][0]]]+=ed[i][2]; } scanf("%I64d",&q); printf("Case %I64d:\n",test); for (i=0;i<q;i++){ scanf("%s",s); if (s[0]=='A'){ scanf("%I64d%I64d",&x,&y); if (x!=y){ printf("%I64d\n",tot[2]); } else { printf("%I64d\n",tot[x]); } } else { scanf("%I64d",&x); y=col[x]; tot[y]-=w[x][y]; tot[1-y]+=w[x][1-y]; tot[2]+=w[x][y]-w[x][1-y]; for (j=edg[x];j<edg[x+1];j++){ w[ed[j][1]][y]-=ed[j][2]; w[ed[j][1]][1-y]+=ed[j][2]; if (y==col[ed[j][1]]){ tot[y]-=ed[j][2]; tot[2]+=ed[j][2]; } else { tot[1-y]+=ed[j][2]; tot[2]-=ed[j][2]; } } col[x]=1-y; } } } return 0; }