bzoj3714: [PA2014]Kuglarz题解
bzoj3714: [PA2014]Kuglarz题解
妥妥的神题,
看到这道题谁会想到最小生成树,
而且kruskal还很难卡过去,即使有20s(人丑自带常数大)
只好又学了一波prim,
感觉还行,跟dijkstra差不多???~~~
所以代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5006,M=200006;
int n,m,cnt=0,p=0,t1,t2,t3,dis[N],v[N],head[N];
ll sum=0;
struct edge{int nxt,to,w;}e[M<<1];
struct xd{
int z,i;
bool operator < (const xd &a) const {return a.z<z;}
}tmp,nw;
priority_queue<xd> q;
inline void add(int u,int v,int w){e[++cnt].nxt=head[u],e[cnt].to=v,e[cnt].w=w,head[u]=cnt;}
void prim(){
memset(dis,0x7f,sizeof(dis));
dis[1]=0,tmp.z=0,tmp.i=1,q.push(tmp);
while(!q.empty()){
tmp=q.top(),q.pop();
if(v[tmp.i]) continue;
v[tmp.i]=1,++p,sum+=tmp.z;
for(int i=head[tmp.i];i;i=e[i].nxt) if(dis[e[i].to]>e[i].w) dis[e[i].to]=e[i].w,nw.i=e[i].to,nw.z=e[i].w,q.push(nw);
}
}
inline int read(){
int T=0,F=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
return F*T;
}
int main(){
n=read(),m=read();
for(int i=1;i<=m;++i) t1=read(),t2=read(),t3=read(),add(t1,t2,t3),add(t2,t1,t3);
prim();
if(p<n) printf("orz\n");
else printf("%lld\n",sum);
return 0;
}
好了好了,下面就来分析分析这一道题,出(sang)得(xin)真(bin)好(kuang):
设\(S_{i}\)为第\(1\)个到第\(i\)个杯子下球的个数的奇偶性,
那么,第\(l\)个杯子到第\(r\)个杯子的奇偶性为\(S_{l-1}\)^\({S_{r}}\)
所以我们从\(l-1\)到\(r\)连一条权值为\(c_{l,r}\)的边,代表若知道\(l\)或者\(r\)的奇偶性,花费\(c_{l,r}\)可以知道另一个的奇偶性。
最后,我们要知道所有点的权值,只要确保图的连通即可(0点的奇偶性为0),用最小生成树求出最小代价。
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5006,M=4000006;
int n,m,cnt=0,p=0,t1,t2,t3,dis[N],v[N],head[N];
ll sum=0;
struct edge{int nxt,to,w;}e[M<<1];
struct xd{
int z,i;
bool operator < (const xd &a) const {return a.z<z;}
}tmp,nw;
priority_queue<xd> q;
inline void add(int u,int v,int w){e[++cnt].nxt=head[u],e[cnt].to=v,e[cnt].w=w,head[u]=cnt;}
void prim(){
memset(dis,0x7f,sizeof(dis));
dis[0]=0,tmp.z=0,tmp.i=0,q.push(tmp);
while(!q.empty()){
tmp=q.top(),q.pop();
if(v[tmp.i]) continue;
v[tmp.i]=1,++p,sum+=tmp.z;
for(int i=head[tmp.i];i;i=e[i].nxt) if(!v[e[i].to]&&dis[e[i].to]>e[i].w) dis[e[i].to]=e[i].w,nw.i=e[i].to,nw.z=e[i].w,q.push(nw);
}
}
inline int read(){
int T=0,F=1; char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
return F*T;
}
int main(){
n=read();
for(int i=1;i<=n;++i) for(int j=i;j<=n;++j) t1=read(),add(i-1,j,t1),add(j,i-1,t1);
prim(),printf("%lld\n",sum);
return 0;
}