题目:http://codeforces.com/problemset/problem/109/C
题意:一棵树n个节点,组成一个图,每条边都有权值,对于i、j、k三个数,计算所有的 i 到 j 和 i 到 k 的路径上有幸运数的三元组个数。
题解:用并查集来做,对于任意节点 i ,找出与 i 连通的且某段路径的权值是幸运数的点的个数num,则总个数即是1~n的num*(num-1).但是因为有些点之间是间接连接的,无法直接判断,所以用并查集来更新,计算出每个点的根节点的num值(额,每个点的num值也无法直接计算,因为有的间接连接的点也符合,但可以通过两点的权值计算点与 i 的不符合的点的个数,用n减去它就是所需的 num)。在后面计算总数时,遍历每个点时用其根节点的num值来计算。
这两天整个人敲题都是迷的.........
1 #include <map> 2 #include <stack> 3 #include <queue> 4 #include <cmath> 5 #include <string> 6 #include <limits> 7 #include <cstdio> 8 #include <vector> 9 #include <cstdlib> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 #define Scc(c) scanf("%c",&c) 14 #define Scs(s) scanf("%s",s) 15 #define Sci(x) scanf("%d",&x) 16 #define Sci2(x, y) scanf("%d%d",&x,&y) 17 #define Sci3(x, y, z) scanf("%d%d%d",&x,&y,&z) 18 #define Scl(x) scanf("%I64d",&x) 19 #define Scl2(x, y) scanf("%I64d%I64d",&x,&y) 20 #define Scl3(x, y, z) scanf("%I64d%I64d%I64d",&x,&y,&z) 21 #define Pri(x) printf("%d ",x) 22 #define Prl(x) printf("%I64d ",x) 23 #define Prc(c) printf("%c ",c) 24 #define Prs(s) printf("%s ",s) 25 #define For(i,x,y) for(int i=x;i<y;i++) 26 #define For_(i,x,y) for(int i=x;i<=y;i++) 27 #define FFor(i,x,y) for(int i=x;i>y;i--) 28 #define FFor_(i,x,y) for(int i=x;i>=y;i--) 29 #define Mem(f, x) memset(f,x,sizeof(f)) 30 #define LL long long 31 #define ULL unsigned long long 32 #define MAXSIZE 100005 33 #define INF 0x3f3f3f3f 34 const int mod=1e9; 35 const double PI = acos(-1.0); 36 37 using namespace std; 38 39 int pre[MAXSIZE]; 40 int num[MAXSIZE]; 41 int find(int x) 42 { 43 if(x!=pre[x]) 44 return pre[x]=find(pre[x]); 45 return x; 46 } 47 int check(int n) 48 { 49 while(n) 50 { 51 if(n%10!=4&&n%10!=7) 52 return 0; 53 n/=10; 54 } 55 return 1; 56 } 57 void hhh(int x,int y) 58 { 59 x=find(x); 60 y=find(y); 61 if(x==y) 62 return ; 63 pre[y]=x; 64 num[x]+=num[y]; 65 } 66 int main() 67 { 68 int n; 69 Sci(n); 70 For_(i,1,n) 71 { 72 num[i]=1; 73 pre[i]=i; 74 } 75 76 int a,b,c; 77 For_(i,1,n-1) 78 { 79 Sci3(a,b,c) ; 80 if(!check(c)) 81 { 82 hhh(a,b); 83 } 84 } 85 LL sum=0; 86 For_(i,1,n) 87 { 88 int tmp=n-num[ find( i) ]; 89 sum+=(LL)(tmp-1)*tmp;//这个地方的(LL)不能省,乘积结果应该是会超出int范围 90 } 91 Prl(sum); 92 return 0; 93 }