Sunteți pe pagina 1din 20

BIT

template<class T>
class BIT {
T *tree;
int maxVal;
public:
BIT(int N) {
tree = new T[N+1];
memset(tree,0,sizeof(T)*(N+1));
maxVal = N;
}
void update(int idx, T val) {
while (idx <= maxVal) {
tree[idx] += val;
idx += (idx & -idx);
}
}
//Returns the cumulative frequency of index idx
T read(int idx) {
T sum=0;
while (idx>0) {
sum += tree[idx];
idx -= (idx & -idx);
}
return sum;
}
};

UNION FIND
#include <vector>
template <class T>
class UnionFind {
vector<T> id(100000), size(100000);
int numSet;
UnionFind(int N) {
numSet = N;
for(int i=0; i<N; i++) {
id[i] = i;
}
size.assign(N,1);
}
int find(int u) {
return (id[u] == u) ? u : (id[u] = find(id[u]));
}
bool sameSet(int u,int v) {
return find(u) == find(v);
}
int count() {
return numSet;
}
int sizeSet(int u) {
return size[find(u)];
}

};

void unionSet(int u, int v) {


int i = find(u);
int j = find(v);
if(i == j) return;
if(size[i] < size[j]) {
id[i] = j;
size[j] += size[i];
} else {
id[j] = i;
size[i] += size[j];
}
numSet--;
}

REC. BACKTRACKING (N-QUEENS)


#include <iostream>
#include <string.h>
#include <math.h>
using namespace std;
int x[9], TC;
bool place(int queen, int row) {
for(int prev = 1; prev <= queen 1; prev++)
for(int prev = 1; prev <= queen 1; prev++)
if(x[prev] == row || (abs(x[prev]-row) == abs(prev-queen))
return false;
return true;
}
void NQueens(int queen) {
for(int row = 1; row<= 8; row++)
if(place(queen, row)) {
//cetak queen or do something
} else
NQueens(queen+1);
}
int main() {
//...
NQueens(1);
}

PRIME NUMBER
#include <iostream>
using namespace std;
bool f[1000000];
int main(){
int n = 1000000;
for(int i=2;i<=n;i++)if(!f[i]){
for(int j=i+i;j<=n;j+=i)f[j]=1;
}
}

FAST DIJKSTRA
// Implementation of Dijkstra's algorithm using adjacency lists
// and priority queue for efficiency.
//
// Running time: O(|E| log |V|)
#include<queue>

#include<stdio.h>
using namespace std;
const int INF = 2000000000;
typedef pair<int,int> PII;
int main() {
int N, s, t;
scanf ("%d%d%d", &N, &s, &t);
vector<vector<PII> > edges(N);
for(int i = 0; i < N; i++) {
int M;
scanf ("%d", &M);
for(int j = 0; j < M; j++) {
int vertex, dist;
scanf ("%d%d", &vertex, &dist);
edges[i].push_back (make_pair (dist, vertex)); // note order of
arguments here
}
}
// use priority queue in which top element has the "smallest" priority
priority_queue<PII, vector<PII>, greater<PII> > Q;
vector<int> dist(N, INF), dad(N, -1);
Q.push (make_pair (0, s));
dist[s] = 0;
while(!Q.empty()) {
PII p = Q.top();
if(p.second == t) break;
Q.pop();
int here = p.second;
for(vector<PII>::iterator it=edges[here].begin(); it!=edges[here].end();
it++) {
if(dist[here] + it->first < dist[it->second]) {
dist[it->second] = dist[here] + it->first;
dad[it->second] = here;
Q.push (make_pair (dist[it->second], it->second));
}
}
}
printf ("%d\n", dist[t]);
if(dist[t] < INF)
for(int i=t; i!=-1; i=dad[i])
printf ("%d%c", i, (i==s?'\n':' '));
return 0;
}

GEOMETRY
const double eps=1e-8;
const double inf=1e20;
const double pi=acos(-1.0);
const int maxp=1111;
int dblcmp(double d) {
if (fabs(d)<eps)return 0;
return d>eps?1:-1;
}
inline double sqr(double x) {
return x*x;
}
struct point {
double x,y;
point() {}
point(double _x,double _y):

};

x(_x),y(_y) {};
void input() {
scanf("%lf%lf",&x,&y);
}
void output() {
printf("%.2f %.2f\n",x,y);
}
bool operator==(point a) {
return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0;
}
bool operator<(point a)const {
return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x;
}
double len() {
return sqrt(len2());
}
double len2() {
return x*x+y*y;
}
double distance(point p) {
return sqrt((p.x-x)*(p.x-x)+(p.y-y)*(p.y-y));
}
point add(point p) {
return point(x+p.x,y+p.y);
}
point sub(point p) {
return point(x-p.x,y-p.y);
}
point mul(double b) {
return point(x*b,y*b);
}
point div(double b) {
return point(x/b,y/b);
}
double dot(point p) {
return x*p.x+y*p.y;
}
double det(point p) {
return x*p.y-y*p.x;
}
double rad(point a,point b) {
point p=*this;
return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));
}
point trunc(double r) {
r/=len();
return point(x*r,y*r);
}
point rotleft() {
return point(-y,x);
}
point rotright() {
return point(y,-x);
}
point rotate(point p,double angle) { // p angle
point v=this->sub(p);
double c=cos(angle),s=sin(angle);
return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
}

struct line {
point a,b;
line() {}
line(point _a,point _b) {
a=_a;
b=_b;
}
bool operator==(line v) {
return (a==v.a)&&(b==v.b);
}
// angle
line(point p,double angle) {
a=p;
if (dblcmp(angle-pi/2)==0) {
b=a.add(point(0,1));
} else {
b=a.add(point(1,tan(angle)));
}
}
line(double _a,double _b,double _c) {
if (dblcmp(_a)==0) {
a=point(0,-_c/_b);
b=point(1,-_c/_b);
} else if (dblcmp(_b)==0) {
a=point(-_c/_a,0);
b=point(-_c/_a,1);
} else {
a=point(0,-_c/_b);
b=point(1,(-_c-_a)/_b);
}
}
void input() {
a.input();
b.input();
}
double length() {
return a.distance(b);
}
//

//1
//2
//3
int relation(point p) {
int c=dblcmp(p.sub(a).det(b.sub(a)));
if (c<0)return 1;
if (c>0)return 2;
return 3;
}
bool pointonseg(point p) {
return
dblcmp(p.sub(a).det(b.sub(a)))==0&&dblcmp(p.sub(a).dot(p.sub(b)))<=0;
}
bool parallel(line v) {
return dblcmp(b.sub(a).det(v.b.sub(v.a)))==0;
}
//2
//1

//0
int segcrossseg(line v) {
int d1=dblcmp(b.sub(a).det(v.a.sub(a)));

int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a)));
int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a)));
if ((d1^d2)==-2&&(d3^d4)==-2)return 2;
return (d1==0&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=0||
d2==0&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=0||
d3==0&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=0||
d4==0&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=0);

}
int linecrossseg(line v) {
int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
if ((d1^d2)==-2)return 2;
return (d1==0||d2==0);
}
int linecrossline(line v) {
if ((*this).parallel(v)) {
return v.relation(a)==3;
}
return 2;
}
point crosspoint(line v) {
double a1=v.b.sub(v.a).det(a.sub(v.a));
double a2=v.b.sub(v.a).det(b.sub(v.a));
return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1));
}
double dispointtoline(point p) {
return fabs(p.sub(a).det(b.sub(a)))/length();
}
double dispointtoseg(point p) {
if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0) {
return min(p.distance(a),p.distance(b));
}
return dispointtoline(p);
}
point lineprog(point p) {
return a.add(b.sub(a).trunc(b.sub(a).dot(p.sub(a))/b.distance(a)));
}
point symmetrypoint(point p) {
point q=lineprog(p);
return point(2*q.x-p.x,2*q.y-p.y);
}

};
struct cmp {
point p;
cmp(const point &p0) {
p=p0;
}
bool operator()(const point &aa,const point &bb) {
point a=aa,b=bb;
int d=dblcmp(a.sub(p).det(b.sub(p)));
if (d==0) {
return dblcmp(a.distance(p)-b.distance(p))<0;
}
return d>0;
}
};
struct polygon {
int n;
point p[maxp];

line l[maxp];
void input() {
for (int i=0; i<n; i++) {
p[i].input();
}
}
void add(point q) {
p[n++]=q;
}
void getline() {
for (int i=0; i<n; i++) {
l[i]=line(p[i],p[(i+1)%n]);
}
}
void norm() {
point mi=p[0];
for (int i=1; i<n; i++)mi=min(mi,p[i]);
sort(p,p+n,cmp(mi));
}
void getconvex(polygon &convex) {
int i,j,k;
sort(p,p+n);
convex.n=n;
for (i=0; i<min(n,2); i++) {
convex.p[i]=p[i];
}
if (n<=2)return;
int &top=convex.n;
top=1;
for (i=2; i<n; i++) {
while (top&&convex.p[top].sub(p[i]).det(convex.p[top1].sub(p[i]))<=0)
top--;
convex.p[++top]=p[i];
}
int temp=top;
convex.p[++top]=p[n-2];
for (i=n-3; i>=0; i--) {
while (top!=temp&&convex.p[top].sub(p[i]).det(convex.p[top1].sub(p[i]))<=0)
top--;
convex.p[++top]=p[i];
}
}
bool isconvex() {
bool s[3];
memset(s,0,sizeof(s));
int i,j,k;
for (i=0; i<n; i++) {
j=(i+1)%n;
k=(j+1)%n;
s[dblcmp(p[j].sub(p[i]).det(p[k].sub(p[i])))+1]=1;
if (s[0]&&s[2])return 0;
}
return 1;
}
//3
//2
//1
//0

int relationpoint(point q) {
int i,j;
for (i=0; i<n; i++) {
if (p[i]==q)return 3;
}
getline();
for (i=0; i<n; i++) {
if (l[i].pointonseg(q))return 2;
}
int cnt=0;
for (i=0; i<n; i++) {
j=(i+1)%n;
int k=dblcmp(q.sub(p[j]).det(p[i].sub(p[j])));
int u=dblcmp(p[i].y-q.y);
int v=dblcmp(p[j].y-q.y);
if (k>0&&u<0&&v>=0)cnt++;
if (k<0&&v<0&&u>=0)cnt--;
}
return cnt!=0;
}
int relationline(line u) {
int i,j,k=0;
getline();
for (i=0; i<n; i++) {
if (l[i].segcrossseg(u)==2)return 1;
if (l[i].segcrossseg(u)==1)k=1;
}
if (!k)return 0;
vector<point>vp;
for (i=0; i<n; i++) {
if (l[i].segcrossseg(u)) {
if (l[i].parallel(u)) {
vp.pb(u.a);
vp.pb(u.b);
vp.pb(l[i].a);
vp.pb(l[i].b);
continue;
}
vp.pb(l[i].crosspoint(u));
}
}
sort(vp.begin(),vp.end());
int sz=vp.size();
for (i=0; i<sz-1; i++) {
point mid=vp[i].add(vp[i+1]).div(2);
if (relationpoint(mid)==1)return 1;
}
return 2;
}
//u

//

void convexcut(line u,polygon &po) {


int i,j,k;
int &top=po.n;
top=0;
for (i=0; i<n; i++) {
int d1=dblcmp(p[i].sub(u.a).det(u.b.sub(u.a)));
int d2=dblcmp(p[(i+1)%n].sub(u.a).det(u.b.sub(u.a)));
if (d1>=0)po.p[top++]=p[i];

if (d1*d2<0)po.p[top++]=u.crosspoint(line(p[i],p[(i+1)%n]));

}
double getcircumference() {
double sum=0;
int i;
for (i=0; i<n; i++) {
sum+=p[i].distance(p[(i+1)%n]);
}
return sum;
}
double getarea() {
double sum=0;
int i;
for (i=0; i<n; i++) {
sum+=p[i].det(p[(i+1)%n]);
}
return fabs(sum)/2;
}
point getbarycentre() {
point ret(0,0);
double area=0;
int i;
for (i=1; i<n-1; i++) {
double tmp=p[i].sub(p[0]).det(p[i+1].sub(p[0]));
if (dblcmp(tmp)==0)continue;
area+=tmp;
ret.x+=(p[0].x+p[i].x+p[i+1].x)/3*tmp;
ret.y+=(p[0].y+p[i].y+p[i+1].y)/3*tmp;
}
if (dblcmp(area))ret=ret.div(area);
return ret;
}
double areaintersection(polygon po) {
}
double areaunion(polygon po) {
return getarea()+po.getarea()-areaintersection(po);
}

};
struct circle {
point p;
double r;
circle() {}
circle(point _p,double _r):
p(_p),r(_r) {};
circle(double x,double y,double _r):
p(point(x,y)),r(_r) {};
circle(point a,point b,point c) {

p=line(a.add(b).div(2),a.add(b).div(2).add(b.sub(a).rotleft())).crosspoint(line(c
.add(b).div(2),c.add(b).div(2).add(b.sub(c).rotleft())));
r=p.distance(a);
}
void input() {
p.input();
scanf("%lf",&r);
}
bool operator==(circle v) {
return ((p==v.p)&&dblcmp(r-v.r)==0);
}

double area() {
return pi*sqr(r);
}
double circumference() {
return 2*pi*r;
}
//0
//1
//2
int relation(point b) {
double dst=b.distance(p);
if (dblcmp(dst-r)<0)return 2;
if (dblcmp(dst-r)==0)return 1;
return 0;
}
int crossseg(line v) {
return dblcmp(v.dispointtoseg(p)-r)<=0;
}
int getcircle(point a,point b,double r,circle&c1,circle&c2) {
circle x(a,r),y(b,r);
int t=x.pointcrosscircle(y,c1.p,c2.p);
if (!t)return 0;
c1.r=c2.r=r;
return t;
}
int pointcrossline(line v,point &p1,point &p2) {
if (!(*this).crossseg(v))return 0;
point a=v.lineprog(p);
double d=v.dispointtoline(p);
d=sqrt(r*r-d*d);
if (dblcmp(d)==0) {
p1=a;
p2=a;
return 1;
}
p1=a.sub(v.b.sub(v.a).trunc(d));
p2=a.add(v.b.sub(v.a).trunc(d));
return 2;
}
//5
//4
//3
//2
//1
int relationcircle(circle v) {
double d=p.distance(v.p);
if (dblcmp(d-r-v.r)>0)return 5;
if (dblcmp(d-r-v.r)==0)return 4;
double l=fabs(r-v.r);
if (dblcmp(d-r-v.r)<0&&dblcmp(d-l)>0)return 3;
if (dblcmp(d-l)==0)return 2;
if (dblcmp(d-l)<0)return 1;
}
int pointcrosscircle(circle v,point &p1,point &p2) {
int rel=relationcircle(v);
if (rel==1||rel==5)return 0;
if (rel==2||rel==4) {
p1=p.add(v.p.sub(p).trunc(r));
p2=p.add(v.p.sub(p).trunc(r));
return 1;

}
double d=p.distance(v.p);
double l=(d+(sqr(r)-sqr(v.r))/d)/2;
double h=sqrt(sqr(r)-sqr(l));
p1=p.add(v.p.sub(p).trunc(l).add(v.p.sub(p).rotleft().trunc(h)));
p2=p.add(v.p.sub(p).trunc(l).add(v.p.sub(p).rotright().trunc(h)));
return 2;

}
void tangentline(point q,line &u,line &v) {
double d=p.distance(q);
double l=sqr(r)/d;
double h=sqrt(sqr(r)-sqr(l));
u=line(q,p.add(q.sub(p).trunc(l).add(q.sub(p).rotleft().trunc(h))));
v=line(q,p.add(q.sub(p).trunc(l).add(q.sub(p).rotright().trunc(h))));
}
double areacircle(circle v) {
int rel=relationcircle(v);
if (rel>=4)return 0.0;
if (rel<=2)return min(area(),v.area());
double d=p.distance(v.p);
double hf=(r+v.r+d)/2.0;
double ss=2*sqrt(hf*(hf-r)*(hf-v.r)*(hf-d));
double a1=acos((r*r+d*d-v.r*v.r)/2.0*r*d);
a1=a1*r*r;
double a2=acos((v.r*v.r+d*d-r*r)/2.0*v.r*d);
a2=a2*v.r*v.r;
return a1+a2-ss;
}
double areatriangle(point a,point b) {
point p1,p2;
line l(a,b);
int t=pointcrossline(l,p1,p2);
double angle;
if (t<=1) {
return fabs(area()*p.rad(a,b)/(2*pi));
}
bool b1=l.pointonseg(p1);
bool b2=l.pointonseg(p2);
if (b1&&b2) {
return fabs(area()*p.rad(a,p1)/(2*pi)+area()*p.rad(p2,b)/(2*pi)
+fabs(p1.sub(p).det(p2.sub(p)))/2.0);
}
if (b1) {
return fabs(area()*p.rad(a,p1)/(2*pi)
+fabs(p1.sub(p).det(b.sub(p))/2.0));
}
if (b2) {
return fabs(area()*p.rad(p2,b)/(2*pi)
+fabs(a.sub(p).det(p2.sub(p))/2.0));
}
return fabs(a.sub(p).det(b.sub(p))/2.0);
}
double areapologon(polygon pl) {
int i,j,k,l,m;
double ans=0;
for (i=0; i<pl.n; i++) {
int j=(i+1)%pl.n;
if (dblcmp(pl.p[j].sub(p).det(pl.p[i].sub(p)))>=0) {
ans+=areatriangle(pl.p[i],pl.p[j]);
} else {

ans-=areatriangle(pl.p[i],pl.p[j]);

}
return fabs(ans);

}
};
const int maxn=500;
struct circles {
circle c[maxn];
int n;
circles() {}
void add(circle cc) {
c[n++]=cc;
}
void init_or() { //

bool v[maxn]= {0};
int i,j,k=0;
for (i=0; i<n; i++) {
for (j=0; j<n; j++) {
if (i==j)continue;
if (c[i].relationcircle(c[j])==1)v[i]=1;
}
}
for (i=0; i<n; i++) {
if (!v[i])c[k++]=c[i];
}
n=k;
}
void init_and() { //

bool v[maxn]= {0};
int i,j,k=0;
for (i=0; i<n; i++) {
for (j=0; j<n; j++) {
if (i==j)continue;
if (c[j].relationcircle(c[i])==1)v[i]=1;
}
}
for (i=0; i<n; i++) {
if (!v[i])c[k++]=c[i];
}
n=k;
}
};
struct halfplane:public line {
double angle;
halfplane() {}
halfplane(point _a,point _b) {
a=_a;
b=_b;
}
void calcangle() {
angle=atan2(b.y-a.y,b.x-a.x);
}
bool operator<(const halfplane &b)const {
return angle<b.angle;
}
};
struct halfplanes {
int n;
halfplane hp[maxp];

};
struct point3 {
double x,y,z;
point3() {}
point3(double _x,double _y,double _z):
x(_x),y(_y),z(_z) {};
void input() {
scanf("%lf%lf%lf",&x,&y,&z);
}
void output() {
printf("%.2lf %.2lf %.2lf",x,y,z);
}
bool operator==(point3 a) {
return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0&&dblcmp(a.z-z)==0;
}
bool operator<(point3 a)const {
return dblcmp(a.x-x)==0?dblcmp(y-a.y)==0?dblcmp(z-a.z)<0:y<a.y:x<a.x;
}
double len() {
return sqrt(len2());
}
double len2() {
return x*x+y*y+z*z;
}
double distance(point3 p) {
return sqrt((p.x-x)*(p.x-x)+(p.y-y)*(p.y-y)+(p.z-z)*(p.z-z));
}
point3 add(point3 p) {
return point3(x+p.x,y+p.y,z+p.z);
}
point3 sub(point3 p) {
return point3(x-p.x,y-p.y,z-p.z);
}
point3 mul(double d) {
return point3(x*d,y*d,z*d);
}
point3 div(double d) {
return point3(x/d,y/d,z/d);
}
double dot(point3 p) {
return x*p.x+y*p.y+z*p.z;
}
point3 det(point3 p) {
return point3(y*p.z-p.y*z,p.x*z-x*p.z,x*p.y-p.x*y);
}
double rad(point3 a,point3 b) {
point3 p=(*this);
return acos(a.sub(p).dot(b.sub(p))/(a.distance(p)*b.distance(p)));
}
point3 trunc(double r) {
r/=len();
return point3(x*r,y*r,z*r);
}
point3 rotate(point3 o,double r) {
}
};
struct line3 {
point3 a,b;
line3() {}
line3(point3 _a,point3 _b) {

a=_a;
b=_b;

}
bool operator==(line3 v) {
return (a==v.a)&&(b==v.b);
}
void input() {
a.input();
b.input();
}
double length() {
return a.distance(b);
}
double dispointtoline(point3 p) {
b.sub(a).det(p.sub(a)).len()/a.distance(b);
}
point3 lineprog(point3 p) {
return a.add(b.sub(a).trunc(b.sub(a).dot(p.sub(a))/b.distance(a)));
}

};
struct plane {
point3 a,b,c;
plane() {}
plane(point3 _a,point3 _b,point3 _c) {
a=_a;
b=_b;
c=_c;
}
void input() {
a.input();
b.input();
c.input();
}
point3 pvec() {
return b.sub(a).det(c.sub(a));
}
};

SEGMENT TREE
#include <cmath>
#include <cstdio>
#include <vector>
using namespace std;
typedef vector<int> vi;
// Segment Tree Library: The segment tree is stored like a heap array
void st_build(vi &st, const vi &A, int vertex, int L, int R) {
if (L == R)
// as L == R, either one is fine
st[vertex] = L;
// store the index
else {
// recursively compute the values in the left and right subtrees
int nL = 2 * vertex, nR = 2 * vertex + 1;
st_build(st, A, nL, L
, (L + R) / 2);
st_build(st, A, nR, (L + R) / 2 + 1, R
);
int lContent = st[nL]
, rContent = st[nR];
int lValue
= A[lContent], rValue
= A[rContent];
st[vertex] = (lValue <= rValue) ? lContent : rContent;
}
}
void st_create(vi &st, const vi &A) {

// if original array size is N,

// the required segment tree array length is 2*2^(floor(log2(N)) + 1);


int len = (int)(2*pow(2.0, floor((log((double)A.size())/log(2.0)) + 1)));
st.assign(len, 0); // create vector of size `len' and fill it with zeroes
st_build(st, A, 1, 0, (int)A.size() - 1);
// recursive build

int st_rmq(vi &st, const vi &A, int vertex, int L, int R, int i, int j) {
if (i > R || j < L) return -1;
// current segment outside query range
if (L >= i && R <= j) return st[vertex];
// inside query range
// compute the min position in the left and right part of the interval
int p1 = st_rmq(st, A, 2 * vertex
, L
, (L+R) / 2, i, j);
int p2 = st_rmq(st, A, 2 * vertex + 1, (L+R) / 2 + 1, R
, i, j);

// return the
if (p1 == -1)
if (p2 == -1)
return (A[p1]

position where the overall minimum is


return p2;
// if we try to access segment outside query
return p1;
// same as above
<= A[p2]) ? p1 : p2;

int st_rmq(vi &st, const vi& A, int i, int j) {


// function overloading
return st_rmq(st, A, 1, 0, (int)A.size() - 1, i, j);
}
int st_update_point(vi &st, vi &A, int node, int b, int e, int idx, int
new_value) {
// this update code is still preliminary, i == j
// must be able to update range in the future!
int i = idx, j = idx;
// if the current interval does not intersect
// the update interval, return this st node value!
if (i > e || j < b)
return st[node];
// if the current interval is included in the update range,
// update that st[node]
if (b == i && e == j) {
A[i] = new_value; // update the underlying array
return st[node] = b; // this index
}
// compute the minimum position in the
// left and right part of the interval
int p1, p2;
p1 = st_update_point(st, A, 2 * node
, b
, (b + e) / 2, idx,
new_value);
p2 = st_update_point(st, A, 2 * node + 1, (b + e) / 2 + 1, e
, idx,
new_value);

// return the position where the overall minimum is


return st[node] = (A[p1] <= A[p2]) ? p1 : p2;

int st_update_point(vi &st, vi &A, int idx, int new_value) {


return st_update_point(st, A, 1, 0, (int)A.size() - 1, idx, new_value);
}
int main() {

int arr[7] = { 8, 7, 3, 9, 5, 1, 10 };
array
vi A(arr, arr + 7);
vi st;
st_create(st, A);

2
5

// the original

printf("
idx
0, 1, 2, 3, 4, 5 , 6\n");
printf("
A is { 8, 7, 3, 9, 5, 1 , 10 }\n");
printf("RMQ(1, 3) = %d\n", st_rmq(st, A, 1, 3));
// answer is index
printf("RMQ(4, 6) = %d\n", st_rmq(st, A, 4, 6));
printf("RMQ(3,
printf("RMQ(0,
printf("RMQ(0,
printf("RMQ(0,

4)
0)
1)
6)

=
=
=
=

%d\n",
%d\n",
%d\n",
%d\n",

st_rmq(st,
st_rmq(st,
st_rmq(st,
st_rmq(st,

A,
A,
A,
A,

3,
0,
0,
0,

4));
0));
1));
6));

// answer is index
//
//
//
//

4
0
1
5

printf("
idx
0, 1, 2, 3, 4, 5 , 6\n");
printf("Now, modify A into { 8, 7, 3, 9, 5, 100, 10 }\n");
st_update_point(st, A, 5, 100); // update A[5] from 1 to 100
printf("These values do not change\n");
printf("RMQ(1, 3) = %d\n", st_rmq(st, A, 1, 3)); // 2
printf("RMQ(3, 4) = %d\n", st_rmq(st, A, 3, 4)); // 4
printf("RMQ(0, 0) = %d\n", st_rmq(st, A, 0, 0)); // 0
printf("RMQ(0, 1) = %d\n", st_rmq(st, A, 0, 1)); // 1
printf("These values change\n");
printf("RMQ(0, 6) = %d\n", st_rmq(st, A, 0, 6)); // 5->2
printf("RMQ(4, 6) = %d\n", st_rmq(st, A, 4, 6)); // 5->4
printf("RMQ(4, 5) = %d\n", st_rmq(st, A, 4, 5)); // 5->4
} // return 0;

GEOMETRY WENDY
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <stack>
#include <iomanip>
#define PI acos(-1)
#define EPS 1e-9
using namespace std;
struct point {
double x;
double y;
point() {
x = y = 0;
}
point(double _x,double _y): x(_x),y(_y) {}
};
struct vec {
double X;
double Y;
vec(point A, point B) {
X = B.x - A.x;
Y = B.y - A.y;
}

};

vec(double _x,double _y):X(_x),Y(_y) {}

struct line {
double A;
double B;
double C;
point s;
point t;
line(point S,point D) {
A = D.y-S.y;
B = S.x-D.x;
C = A*S.x+B*S.y;
s = S;
t = D;
}
line() {}
};
//rotate point
point rotate(point p,double ang) {
double rad = ang*PI/180;
return point(p.x*cos(rad) - p.y * sin(rad), p.x*sin(rad) + p.y + cos(rad) );
}
vec scale(vec v,double s) {
return vec(v.X *s , v.Y *s);
}
point translate(point p , vec v) {
return point(p.x + v.X , p.y + v.Y);
}

//angle of AoB
double angle(point a, point o , point b) {
//return in rad
vec oa(o,a);
vec ob(o,b);
return acos(dot(oa,ob) / (magnitude(oa) * magnitude(ob)));
}
double dist(point A, point B) {
double dx = A.x-B.x;
double dy = A.y-B.y;
return sqrt((dx*dx)+(dy*dy));
}
double linePointDistance(point A, point B, point C,bool isSegment) {
double d = cross(A,B,C)/dist(A,B);
if(isSegment) {
int dot1 = dot(A,B,C);
if(dot1 > 0)return dist(B,C);
int dot2 = dot(B,A,C);
if(dot2 > 0)return dist(A,C);
}
return fabs(d);
}
double areaOfPol(vector<point> p) {
double area = 0;
int N = p.size();

//Dotproduct AB . BC
double dot(point A, point B, point C) {
vec AB(A,B);
vec BC(B,C);
return (AB.X * BC.X) + (AB.Y * BC.Y);
}
//Dotproduct V1 . V2
double dot(vec V1, vec V2) {
return (V1.X*V2.X) + (V1.Y*V2.Y);
}
//Crossproduct AB x AC
double cross(point A, point B, point C) {
vec AB(A,B);
vec AC(B,C);
double cross = AB.X * AC.Y - AB.Y * AC.X;
return cross;
}
//Crossproduct V1 x V2
double cross(vec V1, vec V2) {
return (V1.X * V2.Y) - (V1.Y * V2.X);
}
//magnitude of vector
double magnitude(vec V) {

return sqrt(V.X*V.X + V.Y*V.Y);

for(int i = 1; i+1<N; i++) {


double x1 = p[i].x - p[0].x;
double y1 = p[i].y - p[0].y;
double x2 = p[i+1].x - p[0].x;
double y2 = p[i+1].y - p[0].y;
double cr = x1*y2 - x2*y1;
area += cr;
}
return fabs(area/2.0);

//check line intersection


void lineIntersection(line S, line D) {
double det = S.A*D.B - D.A*S.B;
if(det < EPS) {
} else {
double x =
double y =
cout << "x
cout << "y
}

(D.B*S.C
(S.A*D.C
: " << x
: " << y

- S.B*D.C)/det;
- D.A*S.C)/det;
<< endl;
<< endl;

}
int turn(point p, point q, point r) {
double cr = cross(p,q,r);
if(cr < 0)return -1; //p->q->r is a right turn

if(cr > 0)return 1; //left turn


return 0;

vector<point> CH;
while(!S.empty()) {
CH.push_back(S.top());
S.pop();
}

bool leftTurn(point p, point q, point r) {


return turn(p,q,r) > 0;
}
bool isConvex(vector<point> vp) {
for(int i = 0 ; i+2 < vp.size() ; i++) {
if(!leftTurn(vp[i],vp[i+1],vp[i+2]))return false;
}
return true;
}
//For Convex Hull -> Convex Polygon which cover all the vertex
point pivot;
//angle compare
bool angle_cmp(point a,point b) {
if(cross(pivot,a,b)==0)
return dist(pivot,a) < dist(pivot,b);
double d1x = a.x - pivot.x, d1y = a.y - pivot.y;
double d2x = b.x - pivot.x, d2y = b.x - pivot.y;
return (atan2(d1y,d1x) - atan2(d2y,d2x)) < 0;
}
vector<point> GScan(vector<point> P) {
int i, P0 = 0 , N = P.size();
for(i = 1; i < N ; i++)
if(P[i].y < P[P0].y || (P[i].y == P[P0].y && P[i].x > P[P0].x))
P0 = i;
point temp = P[0];
P[0] = P[P0];
P[P0] = temp;

double area(double a,double b,double c) {


double s = perimeter(a,b,c)/2;
//heron formula
return sqrt(s*(s-a)*(s-b)*(s-c));
}
double rInCircle(double ab, double bc, double ca) {
return area(ab,bc,ca) / (0.5*perimeter(ab,bc,ca));
}
double rInCircle(point a,point b,point c) {
return rInCircle(dist(a,b),dist(b,c),dist(c,a));
}
int centerInCircle(point a,point b,point c,point &center) {
double r = rInCircle(a,b,c);
if(fabs(r) < EPS)return 0;
line l1,l2;
double ratio = dist(a,b) / dist(a,c);
point p = translate(b,scale(vec(b,c),ratio/(1+ratio)));
l1 = line(a,p);
ratio = dist(b,a) / dist(b,c);
p = translate(a,scale(vec(a,c), ratio / (1 + ratio)));
l2 = line(b,p);

stack<point> S;
point prev,now;
//put first and last
S.push(P[N-1]);
S.push(P[0]);

if(leftTurn(prev,now,P[i])) {
S.push(P[i]);//accept
i++;
} else {
S.pop();

CH.pop_back();
return CH;

/*All about triangle(s)*/


double perimeter(double a,double b,double c) {
return a+b+c;
}

pivot = P[0];
sort(++P.begin(),P.end(),angle_cmp);

i = 1;
while(i < N) {
now = S.top();
S.pop();
prev = S.top();
S.push(now);

double det = l1.A*l2.B - l2.A*l1.B;


if(det < EPS) {

} else {
double x = (l2.B*l1.C - l1.B*l2.C)/det;
double y = (l1.A*l2.C - l2.A*l1.C)/det;
center = point(x,y);
}
return 1;

double rCircumCircle(double ab,double bc, double ca) {


return ab * bc * ca / (4.0 * area(ab,bc,ca));
}

double rCircumCircle(point a,point b,point c) {


return rCircumCircle(dist(a,b),dist(b,c),dist(c,a));
}

void countingSort(int k) {
int i, sum, maxi = max(300, n);
// up to 255 ASCII chars or length of n
memset(c, 0, sizeof c);
// clear frequency table
for (i = 0; i < n; i++)
// count the frequency of each rank
c[i + k < n ? RA[i + k] : 0]++;
for (i = sum = 0; i < maxi; i++) {
int t = c[i]; c[i] = sum; sum += t;
}
for (i = 0; i < n; i++)
// shuffle the suffix array if necessary
tempSA[c[SA[i] + k < n ? RA[SA[i] + k] : 0]++] = SA[i];
for (i = 0; i < n; i++)
// update the suffix array SA
SA[i] = tempSA[i];
}

LIS
vector<int> X;
Int maxintc = 1;
vector<int> LIS(X.size());
for(int i = 0; i < X.size(); i++){
LIS[i] = 1;
for(int j=0;j<i;j++)
if(x[j]<=x[i])
LIS[i] = max(LIS[i], LIS[j] + 1);
Maxintc = max(maxintc, LIS[i]);
}

KNAPSACK
for(int i=0; i<=N; i++)v[i][0] = 0;
for(int j=0; j<=MW; j++)v[0][j] = 0;
for(i = 1; i<=N; i++)
for(int j=1;j<=MW; j++){
if(W[i] > j)
V[i][j] = V[i-1][j];
else
V[i][j] = max(V[i-1][j], P[i] + V[i-1][j-W[i]]);
}
ans += V[N][MW];

void computeLCP_slow() {
LCP[0] = 0;
for (int i = 1; i < n; i++) {
int L = 0;
while (T[SA[i] + L] == T[SA[i-1] + L]) L++;
LCP[i] = L;
} }

SUFFIX ARRAY
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
typedef pair<int, int> ii;
#define MAX_N 100010
char T[MAX_N];
int n;
int RA[MAX_N], tempRA[MAX_N];
int SA[MAX_N], tempSA[MAX_N];
int c[MAX_N];
char P[MAX_N];
int m;
int
int
int
and

void constructSA() {
// this version can go up to 100000 characters
int i, k, r;
for (i = 0; i < n; i++) RA[i] = T[i] - '.';
// initial rankings
for (i = 0; i < n; i++) SA[i] = i;
// initial SA: {0, 1, 2, ..., n-1}
for (k = 1; k < n; k <<= 1) {
// repeat sorting process log n times
countingSort(k);
// actually radix sort: sort based on the second item
countingSort(0);
// then (stable) sort based on the first item
tempRA[SA[0]] = r = 0;
// re-ranking; start from rank r = 0
for (i = 1; i < n; i++)
// compare adjacent suffices
tempRA[SA[i]] =
// if same pair => same rank r; otherwise, increase r
(RA[SA[i]] == RA[SA[i-1]] && RA[SA[i]+k] == RA[SA[i-1]+k]) ? r : ++r;
for (i = 0; i < n; i++)
// update the rank array RA
RA[i] = tempRA[i];
} }

// second approach: O(n log n)


// the input string, up to 100K characters
// the length of input string
// rank array and temporary rank array
// suffix array and temporary suffix array
// for counting/radix sort

// the pattern string (for string matching)


// the length of pattern string

Phi[MAX_N];
// for computing longest common prefix
PLCP[MAX_N];
LCP[MAX_N];
// LCP[i] stores the LCP between previous suffix "T + SA[i-1]"
current suffix "T + SA[i]"

bool cmp(int a, int b) { return strcmp(T + a, T + b) < 0; }

// compare suffices

void constructSA_slow() {
// cannot go beyond 1000 characters
for (int i = 0; i < n; i++) SA[i] = i;
// initial SA: {0, 1, 2, ..., n-1}
sort(SA, SA + n, cmp);
// sort: O(n log n) * comparison: O(n) = O(n^2 log n)
}

// default value
// compute LCP by definition
// always reset L to 0
// L-th chars same, increase L

void computeLCP() {
int i, L;
Phi[SA[0]] = -1;
// default value
for (i = 1; i < n; i++)
// compute Phi in O(n)
Phi[SA[i]] = SA[i-1];
// remember which suffix is behind this suffix
for (i = L = 0; i < n; i++) {
// compute Permuted LCP in O(n)
if (Phi[i] == -1) { PLCP[i] = 0; continue; }
// special case
while (T[i + L] == T[Phi[i] + L]) L++;
// L will be increased max n times
PLCP[i] = L;
L = max(L-1, 0);
// L will be decreased max n times
}
for (i = 1; i < n; i++)
// compute LCP in O(n)
LCP[i] = PLCP[SA[i]];
// put the permuted LCP back to the correct position
}
ii stringMatching() {
// string matching in O(m log n)
int lo = 0, hi = n-1, mid = lo;
// valid matching = [0 .. n-1]
while (lo < hi) {
// find lower bound
mid = (lo + hi) / 2;
// this is round down
int res = strncmp(T + SA[mid], P, m);
// try to find P in suffix 'mid'
if (res >= 0) hi = mid;
// prune upper half (notice the >= sign)
else
lo = mid + 1;
// prune lower half including mid

}
// observe `=' in "res >= 0" above
if (strncmp(T + SA[lo], P, m) != 0) return ii(-1, -1);
// if not found
ii ans; ans.first = lo;
lo = 0; hi = n - 1; mid = lo;
while (lo < hi) {
// if lower bound is found, find upper bound
mid = (lo + hi) / 2;
int res = strncmp(T + SA[mid], P, m);
if (res > 0) hi = mid;
// prune upper half
else
lo = mid + 1;
// prune lower half including mid
}
// (notice the selected branch when res == 0)
if (strncmp(T + SA[hi], P, m) != 0) hi--;
// special case
ans.second = hi;
return ans;
} // return lower/upper bound as the first/second item of the pair, respectively
void LRS() {
int i, maxLCP = 0;
char ans[MAX_N];
strcpy(ans, "");

// print out the length and the actual LRS

for (i = 1; i < n; i++)


if (LCP[i] > maxLCP) {
maxLCP = LCP[i];
strncpy(ans, T + SA[i], maxLCP);
ans[maxLCP] = 0;
}
}

// O(n)

int main() {
printf("Enter a string T below, we will compute its Suffix Array:\n");
n = (int)strlen(gets(T));
constructSA_slow();
// O(n^2 log n)
printf("\nThe Suffix Array of string T = '%s' is shown below (O(n^2 log n)
version):\n", T);
printf("i\tSA[i]\tSuffix\n");
for (int i = 0; i < n; i++) printf("%2d\t%2d\t%s\n", i, SA[i], T + SA[i]);
T[n++] = '.';
// important bug fix!
constructSA();
// O(n log n)
printf("\nThe Suffix Array of string T = '%s' is shown below (O(n log n)
version):\n", T);
printf("i\tSA[i]\tSuffix\n");
for (int i = 0; i < n; i++) printf("%2d\t%2d\t%s\n", i, SA[i], T + SA[i]);
computeLCP();
// O(n)
LRS();
// find the longest repeated substring of the first input string

// copy 'len' characters only


// null terminate this

printf("\nNow, enter a string P below, we will try to find P in T:\n");


printf("Enter an empty string to stop this string search demo!\n");
while (m = (int)strlen(gets(P)), m) { // stop when an empty string is entered
ii pos = stringMatching();
if (pos.first != -1 && pos.second != -1) {
printf("%s is found SA [%d .. %d] of %s\n", P, pos.first, pos.second, T);
printf("They are:\n");
for (int i = pos.first; i <= pos.second; i++)
printf(" %s\n", T + SA[i]);
} else printf("%s is not found in %s\n", P, T);
}

printf("\nThe LRS is '%s' with length = %d\n", ans, maxLCP);

int owner(int idx) { return (idx < n-m-1) ? 1 : 2; }


void LCS() {
int i, j, maxLCP = 0, idx = 0;
char ans[MAX_N];
strcpy(ans, "");

// print out the length and the actual LCS

printf("\nRemember, T = '%s'\nNow, enter another string P:\n", T);


// T already has '.' at the back
m = (int)strlen(gets(P));
strcat(T, P);
// append P
strcat(T, "/");
// add '/' at the back
n = (int)strlen(T);
// update n
constructSA();
// O(n log n)
computeLCP();
// O(n)
printf("\nThe LCP information of 'T.P' = '%s':\n", T);
printf("i\tSA[i]\tLCP[i]\tOwner\tSuffix\n");
for (i = 0; i < n; i++)
printf("%2d\t%2d\t%2d\t%2d\t%s\n", i, SA[i], LCP[i], owner(SA[i]), T +
SA[i]);
for (i = 1, maxLCP = -1; i < n; i++)
if (LCP[i] > maxLCP && owner(SA[i]) != owner(SA[i-1])) {
maxLCP = LCP[i];
idx = i;
//strncpy(ans, T + SA[i], maxLCP);
//ans[maxLCP] = 0;
}

strncpy(ans, T + SA[idx], maxLCP);


ans[maxLCP] = 0;
printf("\nThe LCS is '%s' with length = %d\n", ans, maxLCP);

LCS();
}

// find the longest common substring between T and P

return 0;

KMP STRING
void build_failure_function(const string &str, int *temp_arr) {
temp_arr[0] = temp_arr[1] = 0;
for (int i = 2; i <= sz(str); i++) {
temp_arr[i] = -1;
for (int ind = temp_arr[i-1]; temp_arr[i] == -1; ind = temp_arr[ind]) {
if (str[ind] == str[i-1]) {
temp_arr[i] = ind + 1;
} else if (ind == 0) {
temp_arr[i] = 0;
}
}
}
}
void KMP(const string &text, const string &pattern, int *res) {
int *temp_arr = new int[sz(pattern) + 1];
build_failure_function(pattern, temp_arr);

int i = 0;
int ind = 0;
while (i < sz(text)) {
if (text[i] == pattern[ind]) {
res[i] = ++ind;
if (res[i] == sz(pattern)) {
ind = temp_arr[ind];
}
i++;
} else if (ind == 0) {
res[i++] = 0;
} else {
ind = temp_arr[ind];
}
}
delete [] temp_arr;

TEMPLATE AC_RUSH
#define SIZE(X) ((int)(X.size()))//NOTES:SIZE(
#define LENGTH(X) ((int)(X.length()))//NOTES:LENGTH(
#define MP(X,Y) make_pair(X,Y)//NOTES:MP(
typedef long long int64;//NOTES:int64
typedef unsigned long long uint64;//NOTES:uint64
#define two(X) (1<<(X))//NOTES:two(
#define twoL(X) (((int64)(1))<<(X))//NOTES:twoL(
#define contain(S,X) (((S)&two(X))!=0)//NOTES:contain(
#define containL(S,X) (((S)&twoL(X))!=0)//NOTES:containL(
const double pi=acos(-1.0);//NOTES:pi
const double eps=1e-11;//NOTES:eps
template<class T> inline void checkmin(T &a,T b) {
if(b<a) a=b;
//NOTES:checkmin(
}
template<class T> inline void checkmax(T &a,T b) {
if(b>a) a=b;
//NOTES:checkmax(
}
template<class T> inline T sqr(T x) {
return x*x;
//NOTES:sqr
}
typedef pair<int,int> ipair;//NOTES:ipair
template<class T> inline T lowbit(T n) {
return (n^(n-1))&n;
//NOTES:lowbit(
}
template<class T> inline int countbit(T n) {
return (n==0)?0:(1+countbit(n&(n-1)));
//NOTES:countbit(
}
//Numberic Functions
template<class T> inline T gcd(T a,T b) { //NOTES:gcd(
if(a<0)return gcd(-a,b);
if(b<0)return gcd(a,-b);
return (b==0)?a:gcd(b,a%b);
}
template<class T> inline T lcm(T a,T b) { //NOTES:lcm(
if(a<0)return lcm(-a,b);
if(b<0)return lcm(a,-b);
return a*(b/gcd(a,b));
}
template<class T> inline T euclide(T a,T b,T &x,T &y) { //NOTES:euclide(
if(a<0) {
T d=euclide(-a,b,x,y);

x=-x;
return d;

}
if(b<0) {
T d=euclide(a,-b,x,y);
y=-y;
return d;
}
if(b==0) {
x=1;
y=0;
return a;
} else {
T d=euclide(b,a%b,x,y);
T t=x;
x=y;
y=t-(a/b)*y;
return d;
}

}
template<class T> inline vector<pair<T,int> > factorize(T n) { //NOTES:factorize(
vector<pair<T,int> > R;
for (T i=2; n>1;) {
if (n%i==0) {
int C=0;
for (; n%i==0; C++,n/=i);
R.push_back(make_pair(i,C));
}
i++;
if (i>n/i) i=n;
}
if (n>1) R.push_back(make_pair(n,1));
return R;
}
template<class T> inline bool isPrimeNumber(T n) { //NOTES:isPrimeNumber(
if(n<2)return false;
if (n==2) return true;
if (n % 2 == 0) return false;
for (T i=3; i*i<=n; i+=2) if (n%i==0) return false;
return true;
}
template<class T> inline T eularFunction(T n) { //NOTES:eularFunction(
vector<pair<T,int> > R=factorize(n);
T r=n;
for (int i=0; i<R.size(); i++)r=r/R[i].first*(R[i].first-1);
return r;
}
//Matrix Operations
const int MaxMatrixSize=40;//NOTES:MaxMatrixSize
template<class T> inline void showMatrix(int n,T A[MaxMatrixSize][MaxMatrixSize])
{ //NOTES:showMatrix(
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++)cout<<A[i][j];
cout<<endl;
}
}
template<class T> inline T checkMod(T n,T m) {
return (n%m+m)%m;
//NOTES:checkMod(
}

template<class T> inline void identityMatrix(int n,T A[MaxMatrixSize]


[MaxMatrixSize]) { //NOTES:identityMatrix(
for (int i=0; i<n; i++) for (int j=0; j<n; j++) A[i][j]=(i==j)?1:0;
}
template<class T> inline void addMatrix(int n,T C[MaxMatrixSize][MaxMatrixSize],T
A[MaxMatrixSize][MaxMatrixSize],T B[MaxMatrixSize][MaxMatrixSize]) {
//NOTES:addMatrix(
for (int i=0; i<n; i++) for (int j=0; j<n; j++) C[i][j]=A[i][j]+B[i][j];
}
template<class T> inline void subMatrix(int n,T C[MaxMatrixSize][MaxMatrixSize],T
A[MaxMatrixSize][MaxMatrixSize],T B[MaxMatrixSize][MaxMatrixSize]) {
//NOTES:subMatrix(
for (int i=0; i<n; i++) for (int j=0; j<n; j++) C[i][j]=A[i][j]-B[i][j];
}
template<class T> inline void mulMatrix(int n,T C[MaxMatrixSize][MaxMatrixSize],T
_A[MaxMatrixSize][MaxMatrixSize],T _B[MaxMatrixSize][MaxMatrixSize]) {
//NOTES:mulMatrix(
T A[MaxMatrixSize][MaxMatrixSize],B[MaxMatrixSize][MaxMatrixSize];
for (int i=0; i<n; i++) for (int j=0; j<n; j++) A[i][j]=_A[i][j],B[i]
[j]=_B[i][j],C[i][j]=0;
for (int i=0; i<n; i++) for (int j=0; j<n; j++) for (int k=0; k<n; k++) C[i]
[j]+=A[i][k]*B[k][j];
}
template<class T> inline void addModMatrix(int n,T m,T C[MaxMatrixSize]
[MaxMatrixSize],T A[MaxMatrixSize][MaxMatrixSize],T B[MaxMatrixSize]
[MaxMatrixSize]) { //NOTES:addModMatrix(
for (int i=0; i<n; i++) for (int j=0; j<n; j++) C[i][j]=checkMod(A[i][j]+B[i]
[j],m);
}
template<class T> inline void subModMatrix(int n,T m,T C[MaxMatrixSize]
[MaxMatrixSize],T A[MaxMatrixSize][MaxMatrixSize],T B[MaxMatrixSize]
[MaxMatrixSize]) { //NOTES:subModMatrix(
for (int i=0; i<n; i++) for (int j=0; j<n; j++) C[i][j]=checkMod(A[i][j]-B[i]
[j],m);
}
template<class T> inline T multiplyMod(T a,T b,T m) {
return (T)((((int64)(a)*(int64)(b)%(int64)(m))+(int64)(m))%(int64)(m));
//NOTES:multiplyMod(
}
template<class T> inline void mulModMatrix(int n,T m,T C[MaxMatrixSize]
[MaxMatrixSize],T _A[MaxMatrixSize][MaxMatrixSize],T _B[MaxMatrixSize]
[MaxMatrixSize]) { //NOTES:mulModMatrix(
T A[MaxMatrixSize][MaxMatrixSize],B[MaxMatrixSize][MaxMatrixSize];
for (int i=0; i<n; i++) for (int j=0; j<n; j++) A[i][j]=_A[i][j],B[i]
[j]=_B[i][j],C[i][j]=0;
for (int i=0; i<n; i++) for (int j=0; j<n; j++) for (int k=0; k<n; k++) C[i]
[j]=(C[i][j]+multiplyMod(A[i][k],B[k][j],m))%m;
}
template<class T> inline T powerMod(T p,int e,T m) { //NOTES:powerMod(
if(e==0)return 1%m;
else if(e%2==0) {
T t=powerMod(p,e/2,m);
return multiplyMod(t,t,m);
} else return multiplyMod(powerMod(p,e-1,m),p,m);
}
//Point&Line
double dist(double x1,double y1,double x2,double y2) {
return sqrt(sqr(x1-x2)+sqr(y1-y2));
//NOTES:dist(
}
double distR(double x1,double y1,double x2,double y2) {

return sqr(x1-x2)+sqr(y1-y2);
//NOTES:distR(
}
template<class T> T cross(T x0,T y0,T x1,T y1,T x2,T y2) {
return (x1-x0)*(y2-y0)-(x2-x0)*(y1-y0);
//NOTES:cross(
}
int crossOper(double x0,double y0,double x1,double y1,double x2,double y2) {
//NOTES:crossOper(
double t=(x1-x0)*(y2-y0)-(x2-x0)*(y1-y0);
if (fabs(t)<=eps) return 0;
return (t<0)?-1:1;
}
bool isIntersect(double x1,double y1,double x2,double y2,double x3,double
y3,double x4,double y4) { //NOTES:isIntersect(
return crossOper(x1,y1,x2,y2,x3,y3)*crossOper(x1,y1,x2,y2,x4,y4)<0 &&
crossOper(x3,y3,x4,y4,x1,y1)*crossOper(x3,y3,x4,y4,x2,y2)<0;
}
bool isMiddle(double s,double m,double t) {
return fabs(s-m)<=eps || fabs(t-m)<=eps || (s<m)!=(t<m);
//NOTES:isMiddle(
}
//Translator
bool isUpperCase(char c) {
return c>='A' && c<='Z';
//NOTES:isUpperCase(
}
bool isLowerCase(char c) {
return c>='a' && c<='z';
//NOTES:isLowerCase(
}
bool isLetter(char c) {
return c>='A' && c<='Z' || c>='a' && c<='z';
//NOTES:isLetter(
}
bool isDigit(char c) {
return c>='0' && c<='9';
//NOTES:isDigit(
}
char toLowerCase(char c) {
return (isUpperCase(c))?(c+32):c;
//NOTES:toLowerCase(
}
char toUpperCase(char c) {
return (isLowerCase(c))?(c-32):c;
//NOTES:toUpperCase(
}
template<class T> string toString(T n) {
ostringstream ost;
//NOTES:toString(
ost<<n;
ost.flush();
return ost.str();
}
int toInt(string s) {
int r=0;
//NOTES:toInt(
istringstream sin(s);
sin>>r;
return r;
}
int64 toInt64(string s) {
int64 r=0;
//NOTES:toInt64(
istringstream sin(s);
sin>>r;
return r;
}
double toDouble(string s) {
double r=0;
//NOTES:toDouble(
istringstream sin(s);
sin>>r;

return r;
}
template<class T> void stoa(string s,int &n,T A[]) {
n=0;
//NOTES:stoa(
istringstream sin(s);
for(T v; sin>>v; A[n++]=v);
}
template<class T> void atos(int n,T A[],string &s) {
ostringstream sout;
//NOTES:atos(
for(int i=0; i<n; i++) {
if(i>0)sout<<' ';
sout<<A[i];
}
s=sout.str();
}
template<class T> void atov(int n,T A[],vector<T> &vi) {
vi.clear();
//NOTES:atov(
for (int i=0; i<n; i++) vi.push_back(A[i]);
}
template<class T> void vtoa(vector<T> vi,int &n,T A[]) {
n=vi.size();
//NOTES:vtoa(
for (int i=0; i<n; i++)A[i]=vi[i];
}
template<class T> void stov(string s,vector<T> &vi) {
vi.clear();
//NOTES:stov(
istringstream sin(s);
for(T v; sin>>v; vi.push_bakc(v));
}
template<class T> void vtos(vector<T> vi,string &s) {
ostringstream sout;
//NOTES:vtos(
for (int i=0; i<vi.size(); i++) {
if(i>0)sout<<' ';
sout<<vi[i];
}
s=sout.str();
}
//Fraction
template<class T> struct Fraction {
T a,b;
Fraction(T a=0,T b=1);
string toString();
};//NOTES:Fraction
template<class T> Fraction<T>::Fraction(T a,T b) {
T d=gcd(a,b);
a/=d;
b/=d;
if (b<0) a=-a,b=-b;
this->a=a;
this->b=b;
}
template<class T> string Fraction<T>::toString() {
ostringstream sout;
sout<<a<<"/"<<b;
return sout.str();
}
template<class T> Fraction<T> operator+(Fraction<T> p,Fraction<T> q) {
return Fraction<T>(p.a*q.b+q.a*p.b,p.b*q.b);
}
template<class T> Fraction<T> operator-(Fraction<T> p,Fraction<T> q) {
return Fraction<T>(p.a*q.b-q.a*p.b,p.b*q.b);

}
template<class T> Fraction<T> operator*(Fraction<T> p,Fraction<T> q) {
return Fraction<T>(p.a*q.a,p.b*q.b);
}
template<class T> Fraction<T> operator/(Fraction<T> p,Fraction<T> q) {
return Fraction<T>(p.a*q.b,p.b*q.a);
}

GRAPH ALGORITHMS
Strongly Connected Component & Bi-connected Component
cc::graph[x].push_back(y); // x y
result = cc::scc(size); // Strongly Connected Component
f = (connected[i] == connected[j]); // i j SCC ?
cc::bcc(size);
n = cc::cut_vertex_num; //
b = cc::cut_vertex[i]; // i ?
n = cc::cut_edge_num; //
p = cc::cut_edge[i][0], q = cc::cut_edge[i][1]; // i p-q
#include <cstdlib>
#include <vector>
using namespace std;
namespace cc {
const int SIZE = 10000;
vector<int> graph[SIZE];
int connected[SIZE];
int cut_vertex_num;
bool cut_vertex[SIZE];
int cut_edge_num, cut_edge[SIZE][2];
int order[SIZE];
int visit_time[SIZE], finish[SIZE], back[SIZE];
int stack[SIZE], seen[SIZE];
#define MIN(a,b) (a) = ((a)<(b))?(a):(b)
int dfs(int size) {
int top, cnt, cnt2, cnt3;
int i;
cnt = cnt2 = cnt3 = 0;
stack[0] = 0;
for (i = 0 ; i < size ; i++) visit_time[i] = -1;
for (i = 0 ; i < size ; i++) cut_vertex[i] = false; // CUT VERTEX
cut_edge_num = 0; // CUT_EDGE
for (i = 0 ; i < size ; i++) {
if (visit_time[order[i]] == -1) {
top = 1;
stack[top] = order[i];
seen[top] = 0;
visit_time[order[i]] = cnt++;
connected[order[i]] = cnt3++;
int root_child = 0; // CUT VERTEX
while (top > 0) {
int j, now = stack[top];
if (seen[top] == 0) back[now] = visit_time[now]; // NOT FOR SCC
for (j = seen[top] ; j < graph[now].size() ; j++) {
int next = graph[now][j];
if (visit_time[next] == -1) {
if (top == 1) root_child++; // CUT VERTEX
seen[top] = j + 1;
stack[++top] = next;
seen[top] = 0;

visit_time[next] = cnt++;
connected[next] = connected[now];
break;
} else if (top == 1 || next != stack[top - 1]) // NOT FOR SCC
MIN(back[now], visit_time[next]); // NOT FOR SCC

// CUT EDGE

}
if (j == graph[now].size()) {
finish[cnt2++] = now; // NOT FOR BCC
top--;
if (top > 1) {
MIN(back[stack[top]], back[now]); // NOT FOR SCC
if (back[now] >= visit_time[stack[top]]) { // CUT VERTEX
cut_vertex[stack[top]] = true;
cut_vertex_num++;
}
}
if (top > 0 && visit_time[stack[top]] < back[now]) {
cut_edge[cut_edge_num][0] = stack[top];
cut_edge[cut_edge_num][1] = now;
cut_edge_num++;
}

}
}
if (root_child > 1) { // CUT VERTEX
cut_vertex[order[i]] = true;
cut_vertex_num++;
}

}
}
return cnt3; // number of connected component

}
#undef MIN
vector<int> graph_rev[SIZE];
void graph_reverse(int size) {
for (int i = 0 ; i < size ; i++) graph_rev[i].clear();
for (int i = 0 ; i < size ; i++)
for (int j = 0 ; j < graph[i].size() ; j++)
graph_rev[graph[i][j]].push_back(i);
for (int i = 0 ; i < size ; i++) graph[i] = graph_rev[i];
}
int scc(int size) {
int n;
for (int i = 0 ; i < size ; i++) order[i] = i;
dfs(size);
graph_reverse(size);
for (int i = 0 ; i < size ; i++) order[i] = finish[size - i - 1];
n = dfs(size);
graph_reverse(size);
return n;
}
void bcc(int size) {
for (int i = 0 ; i < size ; i++) order [ i ] = i;
dfs(size);
cut_vertex_num = 0;
for (int i = 0 ; i < size ; i++)
if (cut_vertex[i])
cut_vertex_num++;
}
} // namespace cc

Network Flow
netflow::n = XX; //
netflow::capacity[i][j] = XX; // i j
result = netflow::maximum_flow(source, sink);
f = netflow::flow[i][j]; // i j
#include <cstring>
#include <queue>
using namespace std;
namespace netflow {
typedef int val_t;
const int SIZE = 1000;
const val_t INF = 0x7fFFffFF;
int n;
val_t capacity[SIZE][SIZE];
val_t total_flow;
val_t flow[SIZE][SIZE];
int back[SIZE];
inline val_t res(int a, int b) {
return capacity[a][b] - flow[a][b];
}
val_t push_flow(int source, int sink) {
memset(back, -1, sizeof(back));
queue<int> q;
q.push(source);
back[source] = source;
while (!q.empty() && back[sink] == -1) {
int now = q.front();
q.pop();
for (int i = 0 ; i < n ; i++) {
if (res(now, i) > 0 && back[i] == -1) {
back[i] = now;
q.push(i);
}
}
}
if (back[sink] == -1) return 0;
int now, bef;
val_t f = INF;
for (now = sink ; back[now] != -1 ; now = back[now])
f = min(f, res(back[now], now));
for (now = sink ; back[now] != -1 ; now = back[now]) {
bef = back[now];
flow[bef][now] += f;
flow[now][bef] = -flow[bef][now];
}
total_flow += f;
return f;
}
val_t maximum_flow(int source, int sink) {
memset(flow, 0, sizeof(flow));
total_flow = 0;
while (push_flow(source, sink));
return total_flow;
}
} // namespace netflow

Network Flow Speedup


mcmf::init(graph, size); //

result = netflow::maximum_flow(source, sink);


f = netflow::flow[i][j]; // i j
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
struct edge {
int target;
int capacity; // cap_t
};
namespace netflow {
typedef int cap_t; // capacity type
const int SIZE = 5000;
const cap_t CAP_INF = 0x7fFFffFF;
int n;
vector<pair<edge, int> > g;
int p[SIZE];
int dist[SIZE];
cap_t maxcap;
void init(const vector<edge> graph[], int size) {
int i, j;
n = size;
memset(p, -1, sizeof(p));
maxcap = 0;
g.clear();
for (i = 0 ; i < size ; i++) {
for (j = 0 ; j < graph[i].size() ; j++) {
int next = graph[i][j].target;
edge tmp = graph[i][j];
maxcap = max(maxcap, tmp.capacity);
g.push_back(make_pair(tmp, p[i]));
p[i] = g.size() - 1;
tmp.target = i;
tmp.capacity = 0;
g.push_back(make_pair(tmp, p[next]));
p[next] = g.size() - 1;
}
}
}
bool bfs(int s,int t,int delta) {
for (int i = 0 ; i < n ; i++)
dist[i] = n + 1;
queue<int> q;
dist[s] = 0;
q.push(s);
while (!q.empty()) {
int now = q.front();
q.pop();
for (int i = p[now] ; i != -1 ; i = g[i].second) {
int next = g[i].first.target;
if (g[i].first.capacity < delta) continue;
if (dist[next] == n + 1) {
dist[next] = dist[now] + 1;
q.push(next);
}
}
}
return dist[t] != n + 1;
}
cap_t dfs(int now, int t, int delta, cap_t minv = CAP_INF) {

if (now == t) return minv;


for (int i = p[now] ; i != -1 ; i = g[i].second) {
if (g[i].first.capacity < delta) continue;
int next = g[i].first.target;
if (dist[next] == dist[now] + 1) {
cap_t flow = dfs(next, t, delta, min(minv, g[i].first.capacity));
if (flow) {
g[i].first.capacity -= flow;
g[i ^ 1].first.capacity += flow;
return flow;
}
}
}
return 0;

}
cap_t maxflow(int s, int t) {
cap_t delta = 1, totalflow = 0;
while (delta <= maxcap) delta <<= 1;
while (delta >>= 1) {
while (bfs(s, t, delta)) {
cap_t flow;
while (flow = dfs(s, t, delta)) // not ==
totalflow += flow;
}
}
return totalflow;
}
} // namespace netflow

Bipartite Matching
matching::v1 = XX;
matching::v2 = XX; //
matching::graph[x].push_back(y); // x y
result = matching::hopcroft(); //
y = matching::mx[x]; // x
x = matching::my[y]; // y
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
namespace matching {
typedef int val_t;
const int SIZE = 1000;
int v1, v2;
vector<int> graph[SIZE];
int mx[SIZE], my[SIZE];
int total_matching;
int dist[SIZE];
int inf_dist;
bool bfs() {
int x, y;
queue<int> q;
for (x = 0 ; x < v1 ; x++) {
if (mx[x] == -1) {
dist[x] = 0;
q.push(x);
} else
dist[x] = -1;
}
bool flg = false;

while (!q.empty()) {
x = q.front();
q.pop();
for (int i = 0 ; i < graph[x].size() ; i++) {
y = graph[x][i];
if (my[y] == -1) {
inf_dist = dist[x] + 1;
flg = true;
} else if (dist[my[y]] == -1) {
dist[my[y]] = dist[x] + 1;
q.push(my[y]);
}
}
}
return flg;

}
bool dfs(int x) {
if (x == -1) return true;
for (int i = 0 ; i < graph[x].size() ; i++) {
int y = graph[x][i];
int tmp = (my[y] == -1) ? inf_dist : dist[my[y]];
if (tmp == dist[x] + 1 && dfs(my[y])) {
mx[x] = y;
my[y] = x;
return true;
}
}
dist[x] = -1;
return false;
}
int hopcroft() {
memset(mx, -1, sizeof(mx));
memset(my, -1, sizeof(my));
total_matching = 0;
while (bfs()) {
for (int x = 0 ; x < v1 ; x++)
if (mx[x] == -1 && dfs(x))
total_matching++;
}
return total_matching;
}
} // namespace matching

Hungarian Method
hungarian::n = XX; //
hungarian::cost[i][j] = XX; //
result = hungarian::hungarian(); //
y = hungarian::xy[x]; // x
x = hungarian::yx[y]; // y
#include <cstring>
#include <queue>
#include <algorithm>
#include <limits>
using namespace std;
namespace hungarian {
typedef double val_t;
const int SIZE = 100;
const val_t INF = numeric_limits<double>::infinity();
//

inline bool eq(val_t a, val_t b) {


static const double eps = 1e-9;
return (a - eps < b && b < a + eps);
}
int n;
val_t cost[SIZE][SIZE];
int xy[SIZE], yx[SIZE];
int match_num;
val_t lx[SIZE], ly[SIZE];
bool s[SIZE], t[SIZE];
int prev[SIZE];
val_t hungarian() {
memset(xy, -1, sizeof(xy));
memset(yx, -1, sizeof(yx));
memset(ly, 0, sizeof(ly));
match_num = 0;
int x, y;
for (x = 0 ; x < n ; x++) {
lx[x] = cost[x][0];
for (y = 1 ; y < n ; y++)
lx[x] = max(lx[x], cost[x][y]);
}
for (x = 0 ; x < n ; x++)
for (y = 0 ; y < n ; y++)
if (eq(cost[x][y], lx[x] + ly[y]) && yx[y] == -1) {
xy[x] = y;
yx[y] = x;
match_num++;
break;
}
while (match_num < n) {
memset(s, false, sizeof(s));
memset(t, false, sizeof(t));
memset(prev, -1, sizeof(prev));
queue<int> q;
for (x = 0 ; x < n ; x++) {
if (xy[x] == -1) {
q.push(x);
s[x] = true;
break;
}
}
bool flg = false;
while (!q.empty() && !flg) {
x = q.front();
q.pop();
for (y = 0 ; y < n ; y++) {
if (eq(cost[x][y], lx[x] + ly[y])) {
t[y] = true;
if (yx[y] == -1) {
flg = true;
break;
}
if (!s[yx[y]]) {
s[yx[y]] = true;
q.push(yx[y]);
prev[yx[y]] = x;
}
}
}

}
if (flg) {
int t1, t2;
while (x != -1) {
t1 = prev[x];
t2 = xy[x];
xy[x] = y;
yx[y] = x;
x = t1;
y = t2;
}
match_num++;
} else {
val_t alpha = INF;
for (x = 0 ; x < n ; x++) if (s[x])
for (y = 0 ; y < n ; y++) if (!t[y])
alpha = min(alpha, lx[x] + ly[y] - cost[x][y]);
for (x = 0 ; x < n ; x++) if (s[x]) lx[x] -= alpha;
for (y = 0 ; y < n ; y++) if (t[y]) ly[y] += alpha;
}

}
val_t ret = 0;
for (x = 0 ; x < n ; x++)
ret += cost[x][xy[x]];
return ret;

}
} // namespace hungarian

Min-cost Max-flow using Bellman-ford Algorithm


mcmf::init(graph, size); //
result = mcmf::maximum_flow(source, sink); // , pair
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
struct edge {
int target;
int capacity; // cap_t
int cost; // cost_t
};
namespace mcmf {
typedef int cap_t; // capacity type
typedef int cost_t; // cost type
const int SIZE = 300;
const cap_t CAP_INF = 0x7fFFffFF;
const cost_t COST_INF = 0x7fFFffFF;
int n;
vector<pair<pair<int, edge>, int> > g;
int p[SIZE];
cost_t dist[SIZE];
cap_t mincap[SIZE];
int pth[SIZE];
void init(const vector<edge> graph[], int size) {
int i, j;
n = size;
memset(p, -1, sizeof(p));
g.clear();
for (i = 0 ; i < size ; i++) {
for (j = 0 ; j < graph[i].size() ; j++) {
int next = graph[i][j].target;

edge tmp = graph[i][j];


g.push_back(make_pair(make_pair(i, tmp), p[i]));
p[i] = g.size() - 1;
tmp.target = i;
tmp.capacity = 0;
tmp.cost = -tmp.cost;
g.push_back(make_pair(make_pair(next, tmp), p[next]));
p[next] = g.size() - 1;

}
int bellman(int s, int t) {
int i, j;
for (i = 0 ; i < n ; i++) {
dist[i] = COST_INF;
mincap[i] = 0;
}
dist[s] = 0;
mincap[s] = CAP_INF;
bool flg = false;
for (i = 0 ; i < n ; i++) {
flg = false;
for (j = 0 ; j < g.size() ; j++) {
int now, next;
if (g[j].first.second.capacity == 0) continue;
now = g[j].first.first;
next = g[j].first.second.target;
if (dist[now] == COST_INF) continue;
if (dist[now] + g[j].first.second.cost < dist[next]) {
dist[next] = dist[now] + g[j].first.second.cost;
pth[next] = j;
mincap[next] = min(mincap[now], g[j].first.second.capacity);
flg = true;
}
}
if (!flg) break;
}
if (flg) return -1;
return dist[t] != COST_INF ? 1 : 0;
}
pair<cap_t, cost_t> maximum_flow(int source, int sink) {
cap_t total_flow = 0;
cost_t total_cost = 0;
int state;
while ((state = bellman(source,sink)) > 0) {
cap_t f = mincap[sink];
total_flow += f;
total_cost += f * dist[sink];
for (int i = sink ; i != source; i = g[pth[i]].first.first) {
g[pth[i]].first.second.capacity -= f;
g[pth[i] ^ 1].first.second.capacity += f;
}
}
if (state == -1) while (true); // it's NP-Hard
return make_pair(total_flow, total_cost);
}
} // namespace mcmf

Min-cost Max-flow using Dijkstra Algorithm


mcmf::init(graph, size); //

result = mcmf::maximum_flow(source, sink); // , pair


#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#include <functional>
using namespace std;
struct edge {
int target;
int capacity; // cap_t
int cost; // cost_t
};
namespace mcmf {
typedef int cap_t; // capacity type
typedef int cost_t; // cost type
const int SIZE = 5000;
const cap_t CAP_INF = 0x7fFFffFF;
const cost_t COST_INF = 0x7fFFffFF;
int n;
vector<pair<edge, int> > g;
int p[SIZE];
cost_t dist[SIZE];
cap_t mincap[SIZE];
Seoul National University 11
cost_t pi[SIZE];
int pth[SIZE];
int from[SIZE];
bool v[SIZE];
void init(const vector<edge> graph[], int size) {
int i, j;
n = size;
memset(p, -1, sizeof(p));
g.clear();
for (i = 0 ; i < size ; i++) {
for (j = 0 ; j < graph[i].size() ; j++) {
int next = graph[i][j].target;
edge tmp = graph[i][j];
g.push_back(make_pair(tmp, p[i]));
p[i] = g.size() - 1;
tmp.target = i;
tmp.capacity = 0;
tmp.cost = -tmp.cost;
g.push_back(make_pair(tmp, p[next]));
p[next] = g.size() - 1;
}
}
}
int dijkstra(int s, int t) {
typedef pair<cost_t, int> pq_t;
priority_queue<pq_t, vector<pq_t>, greater<pq_t> > pq;
int i;
for (i = 0 ; i < n ; i++) {
dist[i] = COST_INF;
mincap[i] = 0;
v[i] = false;
}
dist[s] = 0;
mincap[s] = CAP_INF;
pq.push(make_pair(0, s));
while (!pq.empty()) {

int now = pq.top().second;


pq.pop();
if (v[now]) continue;
v[now] = true;
for (i = p[now] ; i != -1 ; i = g[i].second) {
int next = g[i].first.target;
if (v[next]) continue;
if (g[i].first.capacity == 0) continue;
cost_t pot = dist[now] + pi[now] - pi[next] + g[i].first.cost;
if (dist[next] > pot) {
dist[next] = pot;
mincap[next] = min(mincap[now], g[i].first.capacity);
pth[next] = i;
from[next] = now;
pq.push(make_pair(dist[next], next));
}
}

}
for (i = 0 ; i < n ; i++) pi[i] += dist[i];
return dist[t] != COST_INF;

}
pair<cap_t, cost_t> maximum_flow(int source, int sink) {
memset(pi, 0, sizeof(pi));
cap_t total_flow = 0;
cost_t total_cost = 0;
while (dijkstra(source, sink)) {
cap_t f = mincap[sink];
total_flow += f;
for (int i = sink ; i != source ; i = from[i]) {
g[pth[i]].first.capacity -= f;
g[pth[i] ^ 1].first.capacity += f;
total_cost += g[pth[i]].first.cost * f;
}
}
return make_pair(total_flow, total_cost);
}
} // namespace mcmf

S-ar putea să vă placă și