• bzoj3206 [Apio2013]道路费用


    Description

    Input

    第一行包含三个由空格隔开的整数N,M和K。接下来的 M行描述最开始的M 条道路
    。这M行中的第i行包含由空格隔开的整数ai,bi和c i,表示有一条在a i和b i之间,费用为c i的双向道路。接下
    来的K行描述新建的K条道路。这 K行中的第i行包含由空格隔开的整数 xi和yi,表示有一条连接城镇xi和yi新道路
    。最后一行包含N个由空格隔开的整数,其中的第j个为pj,表示从城镇j 前往城镇 1的人数。输入也满足以下约束
    条件。1 ≤ N ≤ 100000;1 ≤ K ≤ 20;1 ≤ M ≤ 300000;对每个i和j,1 ≤ ci, pj ≤ 10^6;

    Output

    你的程序必须输出恰好一个整数到标准输出,表示能获得的最大的收入。

    Sample Input

    5 5 1
    3 5 2
    1 2 3
    2 3 5
    2 4 4
    4 3 6
    1 3
    10 20 30 40 50

    Sample Output

    400

    HINT

    在样例中, Mr. Greedy应该将新道路(1,3)的费用设置为 5分钱。在这个费用下,他可以选择道路(3,5),(1,2),(2,4)和(1,3)来最小化总费用,这个费用为   14。从城镇 3出发的 30个人和从城镇 5出发的 50个人将经过新道路前往城镇 1,因此他可以获得为(30+50)_5=400 分钱的最好收入。如果我们这样做,将新道路(1,3)的费用设置为 10分钱。根据传统的限制,Mr. Greedy必须选择(3,5),(1,2),(2,4)和(2,3),因为这是唯一费用最小的集合。因此,在嘉年华的过程中道路(1,3)将没有任何收入。

    正解:最小生成树+搜索。

    这道题还是有点码的,我写了好久。。

    首先$kleq20$,我们可以想到枚举选边的集合,然后计算答案。

    但是有一个问题,原图特别大,我们每次选边计算答案肯定不行,怎么办呢?

    我们可以发现,有一些边是无论如何都会在原图上的,我们只要强制把$k$条边先加进去,再看有哪些边可以和这$k$条边构成最小生成树就行了。

    然后我们可以把原图缩点变成一个$k+1$个点的图,但是边数还是$k^{2}$级别的。

    那么我们可以再去掉那$k$条边,做一遍最小生成树,这样的边是会出现在原图上的,其他边肯定不会在图上,然后边数就变成$k$条了。

    然后我们枚举$k$条边是否在图上,强制把搜索出来的边加进图中,再看这些边的取值。

    只要把没加进图的边在树上走一下,经过的边边权取个$min$就行了。

      1 #include <bits/stdc++.h>
      2 #define il inline
      3 #define RG register
      4 #define ll long long
      5 #define N (300010)
      6 
      7 using namespace std;
      8 
      9 struct E{ int u,v,w; }gg[N],g[N],e[N];
     10 
     11 int bel[N],a[N],st[N],fa[N],vis[N],n,m,k,top,cnt,ecnt;
     12 ll val[N],ans;
     13 
     14 il int gi(){
     15   RG int x=0,q=1; RG char ch=getchar();
     16   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
     17   if (ch=='-') q=-1,ch=getchar();
     18   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
     19   return q*x;
     20 }
     21 
     22 il int cmp(const E &a,const E &b){ return a.w<b.w; }
     23 
     24 il int find(RG int x){ return fa[x]==x ? x : fa[x]=find(fa[x]); }
     25 
     26 struct graph{
     27   
     28   struct edge{ int nt,to,fg; }g[N<<1];
     29   
     30   int head[N],fa[N],dep[N],dis[N],num;
     31   ll sz[N];
     32   
     33   il void insert(RG int from,RG int to,RG int fg){
     34     g[++num]=(edge){head[from],to,fg},head[from]=num; return;
     35   }
     36   
     37   il void dfs1(RG int x,RG int p){
     38     if (!bel[x]) bel[x]=++cnt; val[bel[x]]+=a[x]; RG int v;
     39     for (RG int i=head[x];i;i=g[i].nt){
     40       v=g[i].to; if (v==p) continue;
     41       if (g[i].fg) bel[v]=bel[x]; dfs1(v,x);
     42     }
     43     return;
     44   }
     45   
     46   il void dfs2(RG int x,RG int p){
     47     fa[x]=p,dep[x]=dep[p]+1,sz[x]=val[x],dis[x]=1<<30; RG int v;
     48     for (RG int i=head[x];i;i=g[i].nt){
     49       v=g[i].to; if (v==p) continue;
     50       dfs2(v,x),sz[x]+=sz[v];
     51     }
     52     return;
     53   }
     54   
     55   il void getlca(RG int u,RG int v,RG int w){
     56     while (u!=v){
     57       if (dep[u]<dep[v]) swap(u,v);
     58       dis[u]=min(dis[u],w),u=fa[u];
     59     }
     60     return;
     61   }
     62   
     63   il ll getans(RG int x,RG int p){
     64     RG ll res=0; RG int v;
     65     for (RG int i=head[x];i;i=g[i].nt){
     66       v=g[i].to; if (v==p) continue;
     67       res+=getans(v,x)+1LL*(!g[i].fg)*dis[v]*sz[v];
     68     }
     69     return res;
     70   }
     71   
     72 }G;
     73 
     74 il ll check(){
     75   for (RG int i=1;i<=cnt;++i) fa[i]=i,G.head[i]=0; G.num=0;
     76   for (RG int i=1,x,y;i<=top;++i){
     77     x=find(e[st[i]].u),y=find(e[st[i]].v);
     78     if (x!=y) fa[x]=y,G.insert(e[st[i]].u,e[st[i]].v,0),G.insert(e[st[i]].v,e[st[i]].u,0);
     79   }
     80   for (RG int i=1,x,y;i<=m;++i){
     81     x=find(g[i].u),y=find(g[i].v),vis[i]=0;
     82     if (x!=y) fa[x]=y,vis[i]=1,G.insert(g[i].u,g[i].v,1),G.insert(g[i].v,g[i].u,1);
     83   }
     84   G.dfs2(1,0);
     85   for (RG int i=1;i<=m;++i) if (!vis[i]) G.getlca(g[i].u,g[i].v,g[i].w);
     86   return G.getans(1,0);
     87 }
     88 
     89 il void dfs(RG int x){
     90   if (x>k) ans=max(ans,check());
     91   else st[++top]=x,dfs(x+1),--top,dfs(x+1); return;
     92 }
     93 
     94 int main(){
     95 #ifndef ONLINE_JUDGE
     96   freopen("toll.in","r",stdin);
     97   freopen("toll.out","w",stdout);
     98 #endif
     99   n=gi(),m=gi(),k=gi(); for (RG int i=1;i<=n;++i) fa[i]=i;
    100   for (RG int i=1;i<=m;++i) g[i].u=gi(),g[i].v=gi(),g[i].w=gi();
    101   for (RG int i=1,x,y;i<=k;++i){
    102     e[i].u=gi(),e[i].v=gi(),x=find(e[i].u),y=find(e[i].v);
    103     if (x!=y) fa[x]=y,G.insert(e[i].u,e[i].v,0),G.insert(e[i].v,e[i].u,0);
    104   }
    105   sort(g+1,g+m+1,cmp);
    106   for (RG int i=1,x,y;i<=m;++i){
    107     x=find(g[i].u),y=find(g[i].v);
    108     if (x!=y) fa[x]=y,G.insert(g[i].u,g[i].v,1),G.insert(g[i].v,g[i].u,1);
    109   }
    110   for (RG int i=1;i<=n;++i) a[i]=gi(),fa[i]=i; G.dfs1(1,0);
    111   for (RG int i=1;i<=k;++i) e[i].u=bel[e[i].u],e[i].v=bel[e[i].v];
    112   for (RG int i=1,x,y;i<=m;++i){
    113     g[i].u=bel[g[i].u],g[i].v=bel[g[i].v];
    114     x=find(g[i].u),y=find(g[i].v);
    115     if (x!=y) fa[x]=y,gg[++ecnt]=g[i];
    116   }
    117   m=ecnt; for (RG int i=1;i<=m;++i) g[i]=gg[i];
    118   dfs(1),cout<<ans; return 0;
    119 }
  • 相关阅读:
    算法(Java实现)—— KMP算法
    算法(Java实现)—— 动态规划算法
    算法(Java实现)—— 分治算法
    算法(Java实现)—— 二分搜索算法
    JDBC(八)—— 数据库连接池
    JDBC(七)—— Dao层操作
    JDBC(六)—— 数据库事务
    JDBC(五)—— 批量插入数据
    JDBC(四)—— Blob类型操作
    Myeclipse10.X安装findbugs插件记录
  • 原文地址:https://www.cnblogs.com/wfj2048/p/7615044.html
Copyright © 2020-2023  润新知