I got a homework where I needed to wright a program to find MST of a graph. I tried running it on the school server but I get a run-time error. On big servers like HackerEarth or HackerRank, however, I got correct answers on all test cases. The boundary for the number of edges and vertices is 100000 and for the weight of an edge 10000. Vertices are labeled from 0 to n.
Here is my code:
#include <stdio.h>
#include <algorithm>
using namespace std;
class Edge
{
public:
int x, y;
long long w;
bool operator<(const Edge& next) const;
};
bool Edge::operator<(const Edge& next) const
{
return this->w < next.w;
}
class DisjointSet
{
public:
int parent, rank;
};
DisjointSet set[100100];
Edge edges[100100];
int findWithPathCompression(int x)
{
if(set[x].parent != x)
set[x].parent = findWithPathCompression(set[x].parent);
return set[x].parent;
}
bool unionByRank(int x1, int y1)
{
int x = findWithPathCompression(x1);
int y = findWithPathCompression(y1);
if(x == y)
return false;
if(set[x].rank > set[y].rank)
set[y].parent = x;
else if(set[y].rank > set[x].rank)
set[x].parent = y;
else
{
set[y].parent = x;
set[x].rank++;
}
return true;
}
int main()
{
int n, m, e = 0, c = 0;
long long r = 0;
scanf("%d %d",&n,&m);
for(int i = 0; i <= n; i++)
{
set[i].parent = i;
set[i].rank = 1;
}
for(int i = 0; i < m; i++)
{
scanf("%d %d %lld",&edges[i].x,&edges[i].y,&edges[i].w);
edges[i].x;
edges[i].y;
}
sort(edges,edges + m);
while(e != n - 1)
{
if(unionByRank(edges[c].x,edges[c].y))
{
r += edges[c].w;
e++;
}
c++;
}
printf("%lld\n",r);
}
I have data from a camera in mono 8bit.
This is converted into an int vector using
std::vector<int> grayVector(size);
// convert / copy pointer data into vector: 8 bit
if (static_cast<XI_IMG_FORMAT>(format) == XI_MONO8)
{
quint8* imageIterator = reinterpret_cast<quint8*> (pMemVoid);
for (size_t count = 0; count < size; ++count)
{
grayVector[count] = static_cast<int>(*imageIterator);
imageIterator++;
}
}
Next, I need to convert this into a QImage. If I set the image format to QImage::Format_Mono the app crashes. With QImage::Format_RGB16 I get strippes, and with QImage::Format_RGB32 everything is black.
I would like to know how to do this the best, efficient and correct way?
// convert gray values into QImage data
QImage image = QImage(static_cast<int>(sizeX), static_cat<int>(sizeY), QImage::Format_RGB16);
for ( int y = 0; y < sizeY; ++y )
{
int yoffset = sizeY*y;
QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(y)) ;
for ( int x = 0; x < sizeX ; ++x )
{
int pos = x + yoffset;
int color = grayVector[static_cast<size_t>(pos)];
*line++ = qRgb(color, color, color);
}
}
The conversion to int is unnecessary and you do it in a very inefficient way; all you need is to use the QImage::Format_Grayscale8 available since Qt 5.5 (mid-2015).
Anyway, what you really want is a way to go from XI_IMG to QImage. The default BP_UNSAFE buffering policy should be adequate - the QImage will do a format conversion, so taking the data from XiApi's internal buffer is OK. Thus the following - all of the conversions are implemented in Qt and are quite efficient - much better than most any naive code.
I didn't check whether some Xi formats may need a BGR swap. If so, then the swap can be set to true in the format selection code and the rest will happen automatically.
See also: xiAPI manual.
static QVector<QRgb> grayScaleColorTable() {
static QVector<QRgb> table;
if (table.isEmpty()) {
table.resize(256);
auto *data = table.data();
for (int i = 0; i < table.size(); ++i)
data[i] = qRgb(i, i, i);
}
return table;
}
constexpr QImage::Format grayScaleFormat() {
return (QT_VERSION >= QT_VERSION_CHECK(5,5,0))
? QImage::Format_Grayscale8
: QImage::Format_Indexed8;
}
QImage convertToImage(const XI_IMG *src, QImage::Format f) {
Q_ASSERT(src->fmt == XI_MONO16);
Q_ASSERT((src->padding_x % 2) == 0);
if (src->fmt != XI_MONO16) return {};
const quint16 *s = static_cast<const quint16*>(src->bp);
const int s_pad = src->padding_x/2;
if (f == QImage::Format_BGR30 ||
f == QImage::Format_A2BGR30_Premultiplied ||
f == QImage::Format_RGB30 ||
f == QImage::Format_A2RGB30_Premultiplied)
{
QImage ret{src->width, src->height, f};
Q_ASSERT((ret->bytesPerLine() % 4) == 0);
const int d_pad = ret->bytesPerLine()/4 - ret->width();
quint32 *d = (quint32*)ret.bits();
if (s_pad == d_pad) {
const int N = (src->width + s_pad) * src->height - s_pad;
for (int i = 0; i < N; ++i) {
quint32 const v = (*s++) >> (16-10);
*d++ = 0xC0000000 | v << 20 | v << 10 | v;
}
} else {
for (int j = 0; j < src->height; ++j) {
for (int i = 0; i < src->width; ++i) {
quint32 const v = (*s++) >> (16-10);
*d++ = 0xC0000000u | v << 20 | v << 10 | v;
}
s += s_pad;
d += d_pad;
}
}
return ret;
}
QImage ret{src->width, src->height, grayScaleFormat()};
const int d_pad = ret->bytesPerLine() - ret->width();
auto *d = ret.bits();
if (s_pad == d_pad) {
const int N = (src->width + s_pad) * src->height - s_pad;
for (int i = 0; i < N; ++i) {
*d++ = (*s++) >> 8;
} else {
for (int j = 0; j < src->height; ++j) {
for (int i = 0; i < src->width; ++i)
*d++ = (*s++) >> 8;
s += s_pad;
d += d_pad;
}
}
return ret;
}
QImage fromXiImg(const XI_IMG *src, QImage::Format dstFormat = QImage::Format_ARGB32Premultiplied) {
Q_ASSERT(src->width > 0 && src->height > 0 && src->padding_x >= 0 && src->bp_size > 0);
Q_ASSERT(dstFormat != QImage::Format_Invalid);
bool swap = false;
int srcPixelBytes = 0;
bool externalConvert = false;
QImage::Format srcFormat = QImage::Format_Invalid;
switch (src->fmt) {
case XI_MONO8:
srcPixelBytes = 1;
srcFormat = grayScaleFormat();
break;
case XI_MONO16:
srcPixelBytes = 2;
externalConvert = true;
break;
case XI_RGB24:
srcPixelBytes = 3;
srcFormat = QImage::Format_RGB888;
break;
case XI_RGB32:
srcPixelBytes = 4;
srcFormat = QImage::Format_RGB32;
break;
};
if (srcFormat == QImage::Format_Invalid && !externalConvert) {
qWarning("Unhandled XI_IMG image format");
return {};
}
Q_ASSERT(srcPixelBytes > 0 && srcPixelBytes <= 4);
int bytesPerLine = src->width * srcPixelBytes + src->padding_x;
if ((bytesPerLine * src->height - src->padding_x) > src->bp_size) {
qWarning("Inconsistent XI_IMG data");
return {};
}
QImage ret;
if (!externalConvert)
ret = QImage{static_cast<const uchar*>(src->bp), src->width, src->height,
bytesPerLine, srcFormat};
else
ret = convertToImage(src, dstFormat);
if (ret.format() == QImage::Format_Indexed8)
ret.setColorTable(grayScaleColorTable());
if (ret.format() != dstFormat)
ret = std::move(ret).convertToFormat(dstFormat);
if (swap)
ret = std::move(ret).rgbSwapped();
if (!ret.isDetached()) // ensure that we don't share XI_IMG's data buffer
ret.detach();
return ret;
}
for circle i have tried to check for all points within radius distance from center.For square, i test for all points from bottom-left-corner to upper-right-corner and for triangle i test the signs of determinants as suggested here. I get correct answer while i enter individual values i.e either 1 cirlce or 1 square or 1 triangle , but not when there are >1 of them. E.g for the case:
C 10 10 3
S 9 8 4
T 7 9 10 8 8 10
where C is circle, S is square and T is triangle,and (10,10) is center of circle with radius 3. (9,8) is the left-most corner of square of side 4 and (7,9),(10,8) and (8,10) are the three vertices of the triangle , the total distinct points covered by them is 34 but i am getting 37.
Here's what i've tried:
typedef pair<int,int> point;
set<point>myset;
set<point>::iterator it;
int findDeter(int x1,int y1,int x2,int y2,int x0,int y0)
{
int ret = x1*(y2-y0)-y1*(x2-x0)+(x2*y0-x0*y2)
-x2*(y1-y0)+y2*(x1-x0)-(x1*y0-x0*y1)
+x0*(y1-y2)-y0*(x1-x2)+(x1*y2-x2*y1);
return ret;
}
bool sameSign(int x, int y)
{
if(x==0||y==0)
return true;
return (x >= 0) ^ (y < 0);
}
int main()
{
int t,i,j,k,n;
int x,y,r,x1,y1,len;
int xmax,ymax,xmin,ymin;
int D1,D2,D3;
int ax,ay,bx,by,cx,cy;
char shape,dump;
scanf("%d",&t);
while(t--)
{
myset.clear();
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%c",&dump);
scanf("%c",&shape);
if(shape=='C')
{
scanf("%d %d %d",&x,&y,&r);
for(j=x;j<=x+r;j++)
{
for(k=y;k<=y+r;k++)
{
point p(j,k);
myset.insert(p);
}
}
for(j=x-r;j<x;j++)
{
for(k=y-r;k<y;k++)
{
point p(j,k);
myset.insert(p);
}
}
}
else if(shape=='S')
{
scanf("%d %d %d",&x1,&y1,&len);
for(j=x1;j<=x1+len;j++)
{
for(k=y1;k<=y1+len;k++)
{
point p(j,k);
myset.insert(p);
}
}
}
else
{
//printf("here\n");
scanf("%d %d %d %d %d %d",&ax,&ay,&bx,&by,&cx,&cy);
/*a1=ax;a2=ay;
b1=bx;b2=by;
c1=cx;c2=cy;*/
xmax = max(ax,max(bx,cx));
ymax = max(ay,max(by,cy));
xmin = min(ax,min(bx,cx));
ymin = min(ay,min(by,cy));
/*for each point P check if sum(the determinants PAB,PAC and PBC have the same signs)*/
for(j=xmin;j<=xmax;j++)
{
for(k=ymin;k<=ymax;k++)
{
D1 = findDeter(ax,ay,bx,by,j,k);
//printf("D1 : %d\n",D1);
D2 = findDeter(bx,by,cx,cy,j,k);
//printf("D2 : %d\n",D2);
D3 = findDeter(cx,cy,ax,ay,j,k);
//printf("D3 : %d\n",D3);
if(sameSign(D1,D2)&&sameSign(D2,D3)&&sameSign(D1,D3))
{
//printf("here\n");
point p(j,k);
myset.insert(p);
}
}
}
}
}
printf("%d\n",myset.size());
}
return 0;
}
After refactoring your code heavily so that it was clearer to me what is going on - I'd say the error is in the circle code. I've included the complete refactored code below but the troublesome section amount s to this:
struct Circle
{
int x;
int y;
int r;
void add_covered_points( set<points> & pts ) const
{
for(int j=x;j<=x+r;j++)
{
for(int k=y;k<=y+r;k++)
{
pts.insert(point(j,k));
}
}
for(int j=x-r;j<x;j++)
{
for(int k=y-r;k<y;k++)
{
pts.insert(point(j,k));
}
}
}
};
This seems to add points from two rectangular sections, one above and the other below the center of the circle. I'd expect the code to look more like this:
void add_covered_points( set<points> & pts ) const
{
for(int j=-r;j<=+r;j++)
{
for(int k=-r;k<=+r;k++)
{
if (j*j + k*k < r*r )
{
pts.insert(point(x+j,x+k));
}
}
}
}
Heres the complete refactored case for your reference
typedef pair<int,int> point;
int findDeter(int x1,int y1,int x2,int y2,int x0,int y0)
{
int ret = x1*(y2-y0)-y1*(x2-x0)+(x2*y0-x0*y2)
-x2*(y1-y0)+y2*(x1-x0)-(x1*y0-x0*y1)
+x0*(y1-y2)-y0*(x1-x2)+(x1*y2-x2*y1);
return ret;
}
bool sameSign(int x, int y)
{
if(x==0||y==0)
return true;
return (x >= 0) ^ (y < 0);
}
struct Circle
{
int x;
int y;
int r;
void add_covered_points( set<points> & pts ) const
{
for(int j=x;j<=x+r;j++)
{
for(int k=y;k<=y+r;k++)
{
pts.insert(point(j,k));
}
}
for(int j=x-r;j<x;j++)
{
for(int k=y-r;k<y;k++)
{
pts.insert(point(j,k));
}
}
}
};
struct Square
{
int x1,y1,len;
void add_covered_points( set<points> & pts ) const
{
for(int j=x1;j<=x1+len;j++)
{
for(int k=y1;k<=y1+len;k++)
{
myset.insert(point(j,k));
}
}
}
};
struct Triangle
{
int ax,ay,bx,by,cx,cy;
void add_covered_points( set<points> & pts ) const
{
int xmax = max(ax,max(bx,cx));
int ymax = max(ay,max(by,cy));
int xmin = min(ax,min(bx,cx));
int ymin = min(ay,min(by,cy));
/*for each point P check if sum(the determinants PAB,PAC and PBC have the same signs)*/
for(int j=xmin;j<=xmax;j++)
{
for(int k=ymin;k<=ymax;k++)
{
int D1 = findDeter(ax,ay,bx,by,j,k);
int D2 = findDeter(bx,by,cx,cy,j,k);
int D3 = findDeter(cx,cy,ax,ay,j,k);
if(sameSign(D1,D2)&&sameSign(D2,D3)&&sameSign(D1,D3))
{
pts.insert(point(j,k));
}
}
}
}
};
int main()
{
set<point>myset;
int t;
scanf("%d",&t);
while(t--)
{
myset.clear();
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
char dump;
char shape;
scanf("%c",&dump);
scanf("%c",&shape);
if(shape=='C')
{
Circle c;
scanf("%d %d %d",&c.x,&c.y,&c.r);
c.add_covered_points( myset );
}
else if(shape=='S')
{
Square s;
scanf("%d %d %d",&s.x1,&s.y1,&s.len);
s.add_covered_points( myset );
}
else
{
Triangle t;
int ax,ay,bx,by,cx,cy;
scanf("%d %d %d %d %d %d",&t.ax,&t.ay,&t.bx,&t.by,&t.cx,&t.cy);
t.add_covered_points( myset );
}
}
}
return 0;
}
Pick's theorem is suitable for counting integer points in the interior of simple polygons with integer vertices.
Here we can see solution for circles.