hdu1598 find the most comfortable road【枚举+并查集】
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 6 int tree[205]; 7 struct edge 8 { 9 int s,e,w; 10 }data[1005]; 11 12 bool cmp(const edge&a,const edge&b) 13 { 14 return a.w<b.w; 15 } 16 17 int find(int x) 18 { 19 if( -1==tree[x] ) return x; 20 return tree[x]=find(tree[x]); 21 } 22 23 void merge(int x,int y) 24 { 25 x=find(x); 26 y=find(y); 27 if( x==y ) return; 28 tree[y]=x; 29 } 30 31 int main() 32 { 33 int n,m,Q,u,v,p,q,ans; 34 35 while( ~scanf("%d%d",&n,&m) ) 36 { 37 for(int i=1;i<=m;i++) 38 scanf("%d%d%d",&data[i].s,&data[i].e,&data[i].w); 39 sort(data+1,data+m+1,cmp); 40 scanf("%d",&Q); 41 for(int i=0;i<Q;i++) 42 { 43 scanf("%d%d",&u,&v); 44 bool first=true; 45 q=0; 46 ans=1000005; 47 for(p=1;p<=m;p++) 48 { 49 memset(tree,-1,sizeof(tree)); 50 if( first ) first=false; 51 else 52 { 53 for(int j=p;j<=q;j++) merge(data[j].s,data[j].e); 54 } 55 while( find(u)!=find(v) ) {q++;if( q<=m ) merge(data[q].s,data[q].e);else break;} 56 if( q>m ) break; 57 if( data[q].w-data[p].w<ans ) ans=data[q].w-data[p].w; 58 } 59 if( 1000005==ans ) puts("-1"); 60 else printf("%d\n",ans); 61 } 62 } 63 return 0; 64 } 65 /* 66 枚举+并查集 67 这道题目的风格让我觉得和CF很像。。。 68 找max-min的最小值 69 可以枚举min,按边权从小到大加边,直到找到第一个可以使u,v连通的max(利用并查集),更新ans。 70 71 打CF的时候接触到一种方法:two-point method 72 这里可以类似的用一下,p枚举min,q枚举max,对于p(i+1),可以直接先把边1,……,qi都添加进来,再从qi开始判断是否连通 73 原因是,对于p(i+1),加入1,……,q(i-1)后u,v一定不连通,否则对于pi,qi就不是第一个使u,v连通的max值了。这样少了一些find()的过程。 74 还有如果q>m,就直接break。因为对于之后的min一定不存在可使u,v连通的max了。 75 */