isCircle
和queryBlockSum
isCircle
的时候主要是使用了查并集的方法,使用了一个全局变量HashMap
来维护这个函数的实现,其中的key
为每个人的id,value
是每个对应id的人的最终的父节点的id。每次增加人时,其父节点是他自己。当addRelation
时将第一个变量的id的最终父节点的父节点改为第二个变量的id,从而实现查并集。此外还在实现查并集的时候增加了压缩路径的方法,即在每次遍历父节点时记录起点和终点,再次遍历修改遍历过程中每个点的父节点。queryBlockSum
的处理中,由于使用了查并集和压缩路径的办法使得处理起来十分简单,利用了一个整数容器来记录最终的父节点,然后遍历所有成员的父节点,所拥有的的不同的父节点的个数即函数所需要返回的值。isCircle
函数时,一开始并没有直接使用修改父节点的办法,而是对于各种情况进行讨论判断,使得在函数处理的过程中会出现存在三个点的父节点成为一个三角形互相指向的情况,导致在使用查并集便利时出现死循环的情况,最后经过思考才发现只需要修改其父节点即可。queryLeastConnection
函数。
Edge
用于记录每一条边的起点、终点以及权值,在每次使用AddRelation
时记录。其次使用了一个HashMap pointer
来记录已经存储的符合条件边的两个端点,且和上次作业的isCircle
一样来重新记录其父节点为自己,以及使用变量int sum=0
作为返回值。随后调用该函数时,现将存储着边的容器根据权重由小到大进行排序,随后遍历。由于本函数的意思为计算含有输入变量id的图中的最小路径,所以首先使用上次作业所完成的isCircle
函数来判断边的其中一个端点是否和id的点在一个图中,如果在一个图中,判断两个端点的父节点是否为同一个,如果两个端点的父节点不同那么sum+=value
,并且修改其父节点为同一个。在刚开始实现queryLeastConnection
函数时,想法过于简单导致出现了bug。在最开始的想法中我只记录了端点,如果一条边的两个端点都被记录那么该边就不会被使用。但是后来的测试中发现该算法会出现一个问题,比如
存在四个端点,1 2 3 4,其边的权值从小到大分别为1->2 3->4 2->3 上述算法中就会出现一个问题,在记录前两条边后四个节点都会被记录,导致2->3该边无法被记录
还有一个很弱智的bug,在一次作业中部分异常的抛出需要排序,我实在调用抛出异常之前来进行排序再输入的,在第二次作业时忘记了。后来觉得第一次作业的做法实在愚蠢,自己还是没有改变编程的思想,还是处于面向过程的编程的思维过程中。
在互测的时候queryValueSum
出现了一些tle的情况,在弱测提交之前听说过这种情况,但是以为强测不会检测所以没有认真去优化该函数,结果互测中被hack了好几次。一开始是想的用变量来记录函数结果,且记录是否需要修改即可。但是助教打回了这个修改,后来发现确实由于该修改只能保证部分数据能够过关,但是没有普遍性。随后Goup
类中使用了一个变量来进行维护,在addRelation
时就进行了该结果的修改使得调用函数时直接返回即可。
在互测过程中还出现了一个哭笑不得的bug,被同学们的测评机给测出来了。当时和同学对拍时有一个bug改了很久,后来发现是group的id为79的时候出现的,所以为了方便调试增加了关于该情况的特殊判断的输出,在最后提交的过程中注释了,但是提交的版本忘记更新了,最终导致出现了问题。
sendIndirectMessage
sendIndirectMessage
的时候没有很明白助教的思路的意思,导致自己在更新权重的时候更新的地方出现了一些问题,最终使得提前的break
使得计算错误,最终看同学的代码才明白自己哪里有一点问题。dce
时忘记将对应的message给删除,导致部分情况在HashMap
中会用get
出现了得到的是null
的情况。/*@ public normal_behavior @ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == id2) && @ (\exists int i; 0 <= i && i < advertisers.length; advertisers[i].getId() == id1) && @ getPerson(id2).hasAdvertiser(getAdvertiser(id1)) == false; @ assignable getPerson(ide2).advertisers; @ ensures (\forall Advertiser i; \old(getPerson(id2).hasAdvertiser(i)); @ getPerson(id2).hasAdvertiser(i)); @ ensures \old(getPerson(id2).advertisers.length) == getPerson(id2).advertisers.length - 1; @ ensures getPerson(id2).hasAdvertiser(getAdvertiser(id1)); @ also @ public exceptional_behavior @ signals (advertiserIdNotFoundException e) !(\exists int i; 0 <= i && i < advertisers.length; @ advertisers[i].getId() == id1); @ signals (PersonIdNotFoundException e) (\exists int i; 0 <= i && i < advertisers.length; @ advertisers[i].getId() == id1) && !(\exists int i; 0 <= i && i < people.length; @ people[i].getId() == id2); @ signals (EqualadvertiserIdException e) (\exists int i; 0 <= i && i < advertisers.length; @ advertisers[i].getId() == id1) && (\exists int i; 0 <= i && i < people.length; @ people[i].getId() == id2) && getPerson(id2).advertisers(getAdvertiser(id1)); @*/ public void addAdvertiserToPerson(/*@ non_null @*/int id1,int id2) throws advertiserIdNotFoundException e,PersonIdNotFoundException,EqualadvertiserIdException;
/*@ public normal_behavior @ requires (\exists int i; 0 <= i && i < advertiser.length; advertiser[i].getId() == id1) && @ (\exists int i; 0 <= i && i < getAdvertiser(id1).commodities.length; commodities[i].getId() == id2) @ ensures (\forall commodity i; \old(getAdvertiser(id1).hasCommodities(i)); @ getAdvertiser(id1).hasCommodities(i)); @ ensures \old(getAdvertiser(id2).commodities.length) == getAdvertiser(id1).commodities.length ; @ ensures \result == getAdvertiser(id1).getCommidity(id2).price; @ also @ public exceptional_behavior @ signals (advertiserIdNotFoundException e) !(\exists int i; 0 <= i && i < advertisers.length; @ advertisers[i].getId() == id1); @ signals (CommodityIdNotFoundException e) (\exists int i; 0 <= i && i < advertisers.length; @ advertisers[i].getId() == id1) && !(\exists int i; 0 <= i && i < getAdvertiser(id1).commodities.length.length; @ getAdvertiser(id1).commodities[i].getId() == id2);@/ public int addAdvertiserToPerson(int id1,int id2) throws advertiserIdNotFoundException,CommodityIdNotFoundException;
/*@ public normal_behavior @ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == personId); @ requires (\exists int i; 0 <= i && i < advertiser.length; advertiser[i].getId() == advertiserId) && @ (\exists int i; 0 <= i && i < getAdvertiser(id1).commodities.length; commodities[i].getId() == commodityId) @ ensures getPerson(personId).money = \old(getPerson(personId).money) - getProduct(commodityId).getValue; @ ensures getSaler(advertiserId).getProduct(commodityId).getLeftNum() = \old(getSaler(advertiserId).getProduct(commodityId).getleftNum()) - 1; @also @ public exceptional_behavior @ signals (PeronIdNotFoundException) !(\exists int i; 0 <= i && i < people.length; people[i].getId() == personId); @ also @ public exceptional_behavior @ signals (PeronIdNotFoundException) (\exists int i; 0 <= i && i < people.length; people[i].getId() == personId)&&!(\exists int i; 0 <= i && i < advertiser.length; advertiser[i].getId() == advertiserId); @ also @ public exceptional_behavior @ signals (commodityIdNotFoundException) (\exists int i; 0 <= i && i < people.length; people[i].getId() == personId)&& @(\exists int i; 0 <= i && i < advertiser.length; advertiser[i].getId() == advertiserId)&& @!(\exists int i; 0 <= i && i < getAdvertiser(id1).commodities.length; commodities[i].getId() == commodityId) ; @*/ public /*@ pure @*/void purchaseProduct(int personId, int commodityId, int advertiserId) throws PeronIdNotFoundException, commodityIdNotFoundException;