货车运输 vijos 1843 NOIP2013 D1T3 最大生成树,并查集,(伪·LCA)
Posted JayWang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了货车运输 vijos 1843 NOIP2013 D1T3 最大生成树,并查集,(伪·LCA)相关的知识,希望对你有一定的参考价值。
(本人比较笨,没写LCA,在树上暴力跑过了此题。)
可以证明答案一定在最大生成树上,因为如果答案比最大生成树上的路径更优,那么最大生成树一定不是正确的。反证之。
同时注意到最大生成树过程中是使用了并查集的,所以不会出现某些点“被丢下”的情况,希望读者不必在此纠结。
我们跑完最大生成树之后,已经有了一个并查集,我们用并查集来判断两个点是否联通,若两个点不在一个并查集中,那么他们也一定在原图中不联通,直接输出-1即可。
首先记录X到树根路径上每个点的“路径最大限重”,再用y向根跑,若遇到有记录的节点,就取x的记录和y跑的记录的最小值,输出即可。
附上AC代码
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmath> 5 #include<iostream> 6 using namespace std; 7 template<class T> inline void read(T &_a){ 8 bool f=0;int _ch=getchar();_a=0; 9 while(_ch<‘0‘ || _ch>‘9‘){if(_ch==‘-‘)f=1;_ch=getchar();} 10 while(_ch>=‘0‘ && _ch<=‘9‘){_a=(_a<<1)+(_a<<3)+_ch-‘0‘;_ch=getchar();} 11 if(f)_a=-_a; 12 } 13 14 const int maxn=10001,maxm=50001; 15 int n,m,egcnt,head[maxn],Q,egcnttt,belong[maxn],fa[maxn],tmp[maxn]; 16 bool vis[maxn]; 17 struct edge {int to,next,dis;}w[maxn<<1]; 18 struct edge2{ 19 int from,to,dis; 20 inline bool operator < (const edge2 x) const {return dis>x.dis;} 21 }edg[maxm]; 22 23 inline void addedge2(int from,int to,int dis) 24 { 25 edg[++egcnttt].to=to; 26 edg[egcnttt].from=from; 27 edg[egcnttt].dis=dis; 28 } 29 30 inline void addedge(int from,int to,int dis) 31 { 32 w[++egcnt].to=to; 33 w[egcnt].next=head[from]; 34 w[egcnt].dis=dis; 35 head[from]=egcnt; 36 w[++egcnt].to=from; 37 w[egcnt].next=head[to]; 38 w[egcnt].dis=dis; 39 head[to]=egcnt; 40 } 41 42 int find(int u) 43 { return belong[u]==u?u:belong[u]=find(belong[u]); } 44 45 inline void kruskal() 46 { 47 sort(edg+1,edg+egcnttt+1); 48 for (register int i=1;i<=n;++i) belong[i]=i; 49 for (register int i=1;i<=egcnttt&&egcnt<((n-1)<<1);++i) 50 { 51 int a1=find(edg[i].from); 52 int a2=find(edg[i].to); 53 if(a1!=a2) 54 { 55 belong[a1]=a2; 56 addedge(edg[i].from,edg[i].to,edg[i].dis); 57 } 58 } 59 } 60 61 void dfs_fa(int u) 62 { 63 for (register int i=head[u];i;i=w[i].next) 64 if(!fa[w[i].to]) fa[w[i].to]=u,dfs_fa(w[i].to); 65 } 66 67 inline int solve(int x,int y) 68 { 69 if(!fa[x]) fa[x]=-1,dfs_fa(x); 70 memset(tmp,0x7f,sizeof(tmp)); 71 tmp[x]=10000000; 72 while(x!=-1) 73 { 74 for (register int i=head[x];i;i=w[i].next) 75 if(w[i].to==fa[x]) 76 { 77 tmp[w[i].to]=min(w[i].dis,tmp[x]); 78 break; 79 } 80 x=fa[x]; 81 } 82 int ans=10000000; 83 while(y!=-1) 84 { 85 if(tmp[y]<=10000000) {ans=min(ans,tmp[y]); break;} 86 for (register int i=head[y];i;i=w[i].next) 87 if(w[i].to==fa[y]) 88 { 89 ans=min(w[i].dis,ans); 90 break; 91 } 92 y=fa[y]; 93 } 94 return ans; 95 } 96 97 int main() 98 { 99 read(n); read(m); 100 for (register int i=1,x,y,z;i<=m;++i) read(x),read(y),read(z),addedge2(x,y,z); 101 kruskal(); 102 for (read(Q);Q;--Q) 103 { 104 int x,y; 105 read(x); read(y); 106 int a1=find(x); 107 int a2=find(y); 108 if(a1!=a2) {printf("-1\n"); continue;} 109 printf("%d\n",solve(x,y)); 110 } 111 return 0; 112 }
以上是关于货车运输 vijos 1843 NOIP2013 D1T3 最大生成树,并查集,(伪·LCA)的主要内容,如果未能解决你的问题,请参考以下文章