hdu 4750
参考阳神的博客写的,非常好的一个方法。
题目的意思是:
对于每对点 找出他们之间所有路径中 最长边 的最小值~~~好拗口的!
思路:
直接找出满足要求的太过于麻烦;所以找出不满足条件的,然后用总的数目(n*(n-1))减去不满足的就行;
做法:
因为找的是最长边,所以首先将边和查询都按从小到大排好序。因为满足要满足条件,查询的值要比当前已经访问的边的值要大;
另外,访问了边之后要维护,选用并查集!
感觉这个方法很正确,但是不会证明 = =!
代码:
1 #include<cstdio> 2 #include<algorithm> 3 #define maxn 10005 4 #define maxm 500005 5 using namespace std; 6 7 struct node 8 { 9 int from,to,w; 10 bool operator <(const node &t)const 11 { 12 return w<t.w; 13 } 14 } no[maxm]; 15 16 struct query 17 { 18 int id,w; 19 bool operator <(const query &t)const 20 { 21 return w<t.w; 22 } 23 } q[maxm]; 24 25 int f[maxn],ans[maxm],num[maxn]; 26 27 int find(int x) 28 { 29 int tmp=x; 30 while(x!=f[x]) x=f[x]; 31 while(f[tmp]!=x) 32 { 33 int t=f[tmp]; 34 f[tmp]=x; 35 tmp=t; 36 } 37 return x; 38 } 39 40 int main() 41 { 42 int n,x,y,m,res,t,qq,tot; 43 while(scanf("%d%d",&n,&m)!=EOF) 44 { 45 for(int i=0;i<n;i++)f[i]=i,num[i]=1; 46 for(int i=1; i<=m; i++)scanf("%d%d%d",&no[i].from,&no[i].to,&no[i].w); 47 sort(no+1,no+m+1); 48 scanf("%d",&qq); 49 for(int i=0; i<qq; i++)scanf("%d",&q[i].w),q[i].id=i; 50 sort(q,q+qq); 51 res=0,t=1,tot=(n-1)*n; 52 for(int i=0; i<qq; i++) 53 { 54 int d=q[i].w; 55 while(t<=m&&no[t].w<d) 56 { 57 x=find(no[t].from),y=find(no[t].to); 58 if(x==y){t++;continue;} 59 res+=num[x]*num[y]*2; 60 num[y]+=num[x]; 61 f[x]=y; 62 t++; 63 } 64 ans[q[i].id]=tot-res; 65 } 66 for(int i=0; i<qq; i++)printf("%d\n",ans[i]); 67 } 68 return 0; 69 }