码迷,mamicode.com
首页 > 其他好文 > 详细

货车运输 vijos 1843 NOIP2013 D1T3 最大生成树,并查集,(伪·LCA)

时间:2017-10-26 18:53:20      阅读:187      评论:0      收藏:0      [点我收藏+]

标签:直接   最小   生成   splay   str   代码   set   答案   clu   

本人比较笨,没写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 }
View Code

货车运输 vijos 1843 NOIP2013 D1T3 最大生成树,并查集,(伪·LCA)

标签:直接   最小   生成   splay   str   代码   set   答案   clu   

原文地址:http://www.cnblogs.com/jaywang/p/7738204.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!