题解 P1194 【买礼物】

teafrogsf

2017-10-17 20:46:44

Solution

[博客](http://teafrog26.lofter.com/) 这个题是一个模型转换题。~~也是我第一个独立想模型转换A掉还手打一遍过的题~~ 题目中说明买两个东西有优惠,而且还贴心地把商品价格固定,则我们可以~~根据输入的格式~~想到,把每两个点之间连边。 发现题目说明买全部商品并求价格最小值,那么可以用最小生成树求解。 我个人用的Prim堆优化(因为最近在复习)~~以及pbds大法好~~,特判一下第一个点加一下A就可以了。 我好像**没判图不连通的情况**也过了ORZ 记得一开始确定初始生成树节点~~虽然好像图都连通所以直接1就可以了没关系~~ 上代码。 ```cpp #include<cstdio> #include<ext/pb_ds/priority_queue.hpp> #define neko 5010 #define meko 200010 #define f(i,a,b) for(register int i=a;i<=b;++i) struct node { int u,v,w,next; }e[meko<<1]; int n,m,t,root,ans,side,book[neko],head[neko]; struct cmp { bool operator()(const int &x,const int &y)const {return e[x].w>e[y].w;} }; __gnu_pbds::priority_queue<int,cmp>q; void add(int x,int y,int z) { e[++t].u=x; e[t].v=y; e[t].w=z; e[t].next=head[x]; head[x]=t; } void prim() { int ans=0; book[root]=1; for(int i=head[root];i;i=e[i].next)q.push(i);//存下标 while(!q.empty()&&side<m) { int x=q.top(),v; q.pop(),v=e[x].v; //printf("%d ",x);//check MST if(!book[v]) { ans+=e[x].w,++side; book[v]=1; for(int i=head[v];i;i=e[i].next)if(!book[e[i].v])q.push(i); } }printf("%d\n",ans+n);//A } int main() { int x,y,z; scanf("%d%d",&n,&m); f(i,1,m) f(j,1,m) { scanf("%d",&x); if(x){add(i,j,x);if(!root)root=i;} }prim(); } ```