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;
} 
posted @ 2019-08-08 19:37  lsoi_ljk123  阅读(111)  评论(0编辑  收藏  举报