标签:选择 接下来 define pre max 如何 最好 val 级别
你的程序必须输出恰好一个整数到标准输出,表示能获得的最大的收入。
正解:最小生成树+搜索。
这道题还是有点码的,我写了好久。。
首先$k\leq20$,我们可以想到枚举选边的集合,然后计算答案。
但是有一个问题,原图特别大,我们每次选边计算答案肯定不行,怎么办呢?
我们可以发现,有一些边是无论如何都会在原图上的,我们只要强制把$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,vis[i]=1,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),vis[i]=0; 115 if (x!=y) fa[x]=y,vis[i]=1,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 }
标签:选择 接下来 define pre max 如何 最好 val 级别
原文地址:http://www.cnblogs.com/wfj2048/p/7615044.html