• cogs1439 货车运输 LCA


    填坑进行时……链接:http://cogs.pro/cogs/problem/problem.php?pid=1439

    题意:找出两点间最短路上最大的货运量。

    这题正解是网络流图论里的东西。首先我们可以想到一个图里面,边权最大的边一定是在这个图的最大生成树上面的,那么我们就先跑出最大生成树。

    跑完后,两点间最大边权就可以直接用$LCA$动态查询即可。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int maxn=10005,maxm=50005;
      7 int fa[maxn];
      8 int getfa(int x)
      9 {
     10     return fa[x]==x?x:fa[x]=getfa(fa[x]);
     11 }
     12 void unionn(int x,int y)
     13 {
     14     x=getfa(x),y=getfa(y);
     15     if(x!=y)fa[y]=x;
     16 }
     17 struct node
     18 {
     19     int from,to,dis,next;
     20 }edge[maxn<<1],tmp[maxm];
     21 int head[maxn],tot;
     22 void addedge(int u,int v,int w)
     23 {
     24     edge[++tot]=(node){u,v,w,head[u]};head[u]=tot;
     25 }
     26 int cmp(const node &a,const node &b)
     27 {
     28     return a.dis>b.dis;
     29 }
     30 int n,m,q;
     31 void Kruskal()
     32 {
     33     for(int i=1;i<=n;i++)fa[i]=i;
     34     int cnt=0;
     35     sort(tmp+1,tmp+m+1,cmp);
     36     for(int i=1;i<=m;i++)
     37     {
     38         int u=tmp[i].from,v=tmp[i].to;
     39         if(getfa(u)!=getfa(v))
     40         {
     41             unionn(u,v);
     42             int w=tmp[i].dis;
     43             addedge(u,v,w);addedge(v,u,w);cnt++;
     44             if(cnt==n-1)break;
     45         }
     46     }
     47 }
     48 int p[maxn][32],dep[maxn],dis[maxn][32];
     49 void dfs(int u,int dept,int fa)
     50 {
     51     dep[u]=dept;
     52     for(int i=head[u];i;i=edge[i].next)
     53     {
     54         int v=edge[i].to;
     55         if(v!=p[u][0])
     56         {
     57             p[v][0]=u;dis[v][0]=edge[i].dis;
     58             dfs(v,dept+1,fa);
     59         }
     60     }
     61 }
     62 void init()
     63 {
     64     for(int i=1;(1<<i)<=n;i++)
     65         for(int j=1;j<=n;j++)p[j][i]=-1,dis[j][i]=2147483647;
     66     for(int j=1;(1<<j)<=n;j++)
     67         for(int i=1;i<=n;i++)
     68             if(p[i][j-1]!=-1)p[i][j]=p[p[i][j-1]][j-1],dis[i][j]=min(dis[i][j-1],dis[p[i][j-1]][j-1]);
     69 }
     70 int lca(int x,int y)
     71 {
     72     int i,res=2147483647;if(dep[x]<dep[y])swap(x,y);
     73     for(i=0;(1<<i)<=dep[x];i++);i--;
     74     for(int j=i;j>=0;j--)
     75         if(dep[x]-(1<<j)>=dep[y])res=min(res,dis[x][j]),x=p[x][j];
     76     if(x!=y)
     77     {
     78         for(int j=i;j>=0;j--)
     79             if(p[x][j]!=p[y][j])res=min(res,min(dis[x][j],dis[y][j])),x=p[x][j],y=p[y][j];
     80         res=min(res,min(dis[x][0],dis[y][0]));
     81     }
     82     return res;
     83 }
     84 int haha()
     85 {
     86     freopen("truck.in","r",stdin);
     87     freopen("truck.out","w",stdout);
     88     scanf("%d%d",&n,&m);
     89     for(int i=1;i<=m;i++)
     90     {
     91         int x,y,z;scanf("%d%d%d",&x,&y,&z);
     92         tmp[i]=(node){x,y,z,0};
     93     }
     94     Kruskal();dfs(1,1,0);init();
     95     scanf("%d",&q);
     96     for(int i=1;i<=q;i++)
     97     {
     98         int x,y;scanf("%d%d",&x,&y);
     99         if(getfa(x)!=getfa(y))puts("-1");
    100         else printf("%d
    ",lca(x,y));
    101     }
    102 }
    103 int sb=haha();
    104 int main(){;}
    cogs1439
  • 相关阅读:
    二分+树状数组/线段树(区间更新) HDOJ 4339 Query
    数论(GCD) HDOJ 4320 Arcane Numbers 1
    拓扑排序/DFS HDOJ 4324 Triangle LOVE
    离散化+线段树/二分查找/尺取法 HDOJ 4325 Flowers
    KMP HDOJ 4300 Clairewd's message
    高精度模板
    前缀+排序 HDOJ 4311 Meeting point-1
    Kruskal HDOJ 4313 Matrix
    最短路(Dijkstra) HDOJ 4318 Power transmission
    (转)C语言运算符优先级 详细列表
  • 原文地址:https://www.cnblogs.com/Loser-of-Life/p/7347947.html
Copyright © 2020-2023  润新知