c++简单算法模板 数据结构

矩阵快速幂

斐波那契数列

简单的快速求斐波那契数列某一项

#include <iostream>
#define N 2		//a[N][N]
using namespace std;
int MOD;		//avoid being too big
struct matrix{
	long long a[N][N];
	matrix(){
		for(int i=0;i<N;i++)
			for(int j=0;j<N;j++)
				a[i][j]=0;
	}
	matrix operator * (const matrix &y){
		matrix z;
		for(int i=0;i<N;i++){
			for(int j=0;j<N;j++){
				for(int k=0;k<N;k++)
					z.a[i][j]+=a[i][k]*y.a[k][j]%MOD;	
				z.a[i][j]%=MOD;
			}
		}
		return z;
	}
};
matrix mat_pow(matrix res, int n){
	/** matrix multiply, only for N==2
		c=(1 1)
		  (1 0)
		res=(f(2)  0  )
  			( 0   f(1))
		return: res (res.a[0][0]+res.a[0][1]==the number of Fab[n])
	**/
	/*int return
	if(n==1) return (res.a[1][0]+res.a[1][1])%MOD;
	if(n==2) return (res.a[0][0]+res.a[0][1])%MOD;
	*/
	/*matrix return*/
	if(n<=2) return res;
	n-=2;
	matrix c;
	c.a[0][0]=c.a[0][1]=c.a[1][0]=1;c.a[1][1]=0;
	while(n){
		if(n&1) res=res*c;
		c=c*c;
		n/=2;
	}
	//int: return (res.a[0][0]+res.a[0][1])%MOD;
	return res;
}
int quick_pow(int x, int y, int n) {
	if(n==0)return x%MOD;
	if(n==1)return y%MOD;
	matrix ans,tmp;
	tmp.a[0][0]=1;
	ans.a[0][0]=(x+y)%MOD;
	for (int i=0;i<N;++i) {
		tmp.a[i][1-i]=1;
		ans.a[i][1-i]=y%MOD;
	}
	n-=2;
	while(n){
		if(n&1)ans=ans*tmp;
		n/=2;
		tmp=tmp*tmp;
	}
	return ans.a[0][0];
}
int main(){
	int T;
	scanf("%d",&T);
	for(int i=1;i<=T;i++){
		int a,b,n,m;
		scanf("%d%d%d%d",&a,&b,&n,&m);
		MOD=1;while(m--) MOD*=10;
		matrix res;
		res.a[0][0]=a+b;res.a[1][1]=b;
		matrix t=mat_pow(res,n);
		int fab;
		if(n==1) fab=(t.a[1][0]+t.a[1][1])%MOD;
		else fab=(t.a[0][0]+t.a[0][1])%MOD;
		printf("%d\n",fab);
	}
	return 0;
}

并查集

简单的并查集

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <list>
#define Swap(a,b) {a=a^b;b=b^a;a=a^b;}
using namespace std;
int n,m;
int parent[50005];
int root(int x){
	int r=x,tmp;
	while(r!=parent[r]) r=parent[r];
	while(x!=r){
		tmp=parent[x];parent[x]=r;x=tmp;
	}
	return x;
}
//int find(int x){return x==fi[x]?x:fi[x]=find(fi[x]);}
void Union(int a,int b){
	int ap=root(a),bp=root(b);
	if(ap==bp) return;
	if(ap<bp){
		parent[bp]=ap;
	}else{
		parent[ap]=bp;
	}
}
int main(){
	int kase=0;
	while(scanf("%d%d",&n,&m)!=EOF&&(n!=0||m!=0)){
		for(int i=0;i<=n;i++){
			parent[i]=i;
		}
		while(m--){
			int k,one,oth;
			scanf("%d%d",&k,&one);
			//while()
				scanf("%d",&oth);
				Union(one,oth);
		}
		printf("Case %d: %d\n",++kase,m);
	}
	
	return 0;
}

前中后序输入

给予前序和中序 或 后序和中序 建树:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <list>
#define Swap(a,b) {a=a^b;b=b^a;a=a^b;}
#define max(a,b) (a>b?a:b)
#define INF 0x3f3f3f3f
using namespace std;

int preorder[100005],inorder[100005],postorder[100005];
typedef struct node{
	int val;
	node *left,*right;
	node(int x){
		val=x;left=right=NULL;
	}
}node;
map<int,node*>getNode;		//get &node by int from tree
map<int,int>pos;			//get position by int from inorder

node *builtByPreIn(node *root,int prel,int prer,int inl,int inr){
	root=new node(preorder[prel]);
	getNode[preorder[prel]]=root;	//register current node
	int i;
	i=pos[preorder[prel]];			//find root's value correspond position in inorder
	//for(i=inl;i<=inr;i++) if(inorder[i]==preorder[prel]) break;
	if(i!=inl){//has left child
		root->left=builtByPreIn(root->left,prel+1,prel+i-inl,inl,i-1);	//i-inl: left children's number
	}
	if(i!=inr){//has right child
		root->right=builtByPreIn(root->right,prel+i-inl+1,prer,i+1,inr);	
	}
	return root;
}

node *builtByPostIn(node *root,int postl,int postr,int inl,int inr){
	root=new node(postorder[postr]);
	getNode[postorder[postr]]=root;	//register current node
	int i;
	i=pos[postorder[postr]];			//find root's value correspond position in inorder
	//for(i=inl;i<=inr;i++) if(inorder[i]==postorder[postr]) break;
	if(i!=inl){//has left child
		root->left=builtByPostIn(root->left,postl,postl+i-inl-1,inl,i-1);	//inr-i: right children's number
	}
	if(i!=inr){//has right child
		root->right=builtByPostIn(root->right,postr-(inr-i),postr-1,i+1,inr);	
	}
	return root;
}

void preorderTraverse(node *cur){
	if(cur) cout<<cur->val<<' ';
	if(cur->left)preorderTraverse(cur->left);
	if(cur->right)preorderTraverse(cur->right);
}
void inorderTraverse(node *cur){
	if(cur->left)inorderTraverse(cur->left);
	if(cur) cout<<cur->val<<' ';
	if(cur->right)inorderTraverse(cur->right);
}
void postorderTraverse(node *cur){
	if(cur->left)postorderTraverse(cur->left);
	if(cur->right)postorderTraverse(cur->right);
	if(cur) cout<<cur->val<<' ';
}



int main(){
	/* pre & in & post
	8
	5 3 7 2 6 4 8 1
	7 2 3 4 6 5 1 8
	2 7 4 6 3 1 8 5
	*/
	
	int n;	//n: node numbers
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&preorder[i]);		//input preorder
	for(int i=1;i<=n;i++){								//input inorder
		scanf("%d",&inorder[i]);
		pos[inorder[i]]=i;
	}
	for(int i=1;i<=n;i++) scanf("%d",&postorder[i]);	//input postorder
	
	node *tree=NULL;
	tree=builtByPostIn(tree,1,n,1,n);
	
	cout<<"pre order: ";preorderTraverse(tree);cout<<endl;
	cout<<"in order: ";inorderTraverse(tree);cout<<endl;
	cout<<"post order: ";postorderTraverse(tree);cout<<endl;
	return 0;
}

带乘法线段树

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <list>
#define Swap(a,b) {a=a^b;b=b^a;a=a^b;}
#define INF 0x3f3f3f3f
#define INFll 0x3f3f3f3f3f3f3f3fll
using namespace std;
long long MOD;int n;
struct node{
	int ll,rr;
	long long val,mul,add;
	node(){
		ll=rr=0;val=0ll;mul=1ll;add=0ll;
	}
}tree[400005];
void build(int curpos,int l,int r){
	tree[curpos].ll=l;tree[curpos].rr=r;
	if(l==r){
		scanf("%lld",&tree[curpos].val);
		return;
	}
	int m=(l+r)/2;
	build(curpos*2,l,m);
	build(curpos*2+1,m+1,r);
	tree[curpos].val=(tree[curpos*2].val+tree[curpos*2+1].val)%MOD;
}
void down(int curpos){
	tree[curpos*2].val=(tree[curpos*2].val*tree[curpos].mul+tree[curpos].add*(tree[curpos*2].rr-tree[curpos*2].ll+1))%MOD;
	tree[curpos*2+1].val=(tree[curpos*2+1].val*tree[curpos].mul+tree[curpos].add*(tree[curpos*2+1].rr-tree[curpos*2+1].ll+1))%MOD;
	tree[curpos*2].mul=(tree[curpos*2].mul*tree[curpos].mul)%MOD;
	tree[curpos*2+1].mul=(tree[curpos*2+1].mul*tree[curpos].mul)%MOD;
	tree[curpos*2].add=(tree[curpos*2].add*tree[curpos].mul+tree[curpos].add)%MOD;
	tree[curpos*2+1].add=(tree[curpos*2+1].add*tree[curpos].mul+tree[curpos].add)%MOD;
	tree[curpos].mul=1ll;
	tree[curpos].add=0ll;
}
int _left,_right,delta;
long long ans;
void add_range(int curpos){
	if(tree[curpos].ll>=_left&&tree[curpos].rr<=_right){
		tree[curpos].val=(tree[curpos].val+(tree[curpos].rr-tree[curpos].ll+1)*delta)%MOD;
		tree[curpos].add=(tree[curpos].add+delta)%MOD;
		return;
	}
	down(curpos);
	int m=(tree[curpos].ll+tree[curpos].rr)/2;
	if(_left<=m) add_range(curpos*2);
	if(_right>m) add_range(curpos*2+1);
	tree[curpos].val=(tree[curpos*2].val+tree[curpos*2+1].val)%MOD;
}
void mul_range(int curpos){
	if(_left<=tree[curpos].ll&&tree[curpos].rr<=_right){
		tree[curpos].val=(tree[curpos].val*delta)%MOD;
		tree[curpos].mul=(tree[curpos].mul*delta)%MOD;
		tree[curpos].add=(tree[curpos].add*delta)%MOD;
		return;
	}
	down(curpos);
	int m=(tree[curpos].ll+tree[curpos].rr)/2;
	if(_left<=m) mul_range(curpos*2);
	if(_right>m) mul_range(curpos*2+1);
	tree[curpos].val=(tree[curpos*2].val+tree[curpos*2+1].val)%MOD;
}
void ask_range(int curpos){
	if(_left<=tree[curpos].ll&&tree[curpos].rr<=_right){
		ans=(tree[curpos].val+ans)%MOD;
		return;
	}
	down(curpos);
	int m=(tree[curpos].ll+tree[curpos].rr)/2;
	if(_left<=m) ask_range(curpos*2);
	if(_right>m) ask_range(curpos*2+1);
}
int main(){
	int m;
	scanf("%d%d%lld",&n,&m,&MOD);
	build(1,1,n);
	//cout<<"---------"<<endl;
	//_left=1;_right=2;ask_range(1);
	//cout<<ans<<endl;
	while(m--){
		int opt;
		scanf("%d%d%d",&opt,&_left,&_right);
		if(opt==1){
			scanf("%d",&delta);
			mul_range(1);
		}else if(opt==2){
			scanf("%d",&delta);
			add_range(1);
		}else if(opt==3){
			ans=0ll;
			ask_range(1);
			printf("%lld\n",(ans+MOD)%MOD);
		}
	}
	
    return 0;
}

笛卡尔树

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <list>
#define Swap(a,b) {a=a^b;b=b^a;a=a^b;}
using namespace std;
const int N = 4000004 , INF = 0x3f3f3f3f;

int root;

struct node
{
    int val , pri , fat , id , son[2];// val遵守二叉搜索树规则,pri遵守堆的规则
    friend bool operator < (node a , node b)
    {
        return a.val < b.val;
    }
    void init(int val_ , int pri_ , int fat_ , int id_)
    {
        val = val_ , pri = pri_ , fat = fat_ , id = id_;
        son[0] = son[1] = 0;
    }
}tr[N];

int stk[N] , top;
int ans_fat[N] , ans_l[N] , ans_r[N];

int car_build(int n)
{
    top = 0;
    for(int i = 1 ; i <= n ; i++)
    {
        int k = top;//k是在栈上移动的指针
        while(k > 0 && tr[stk[k-1]].pri > tr[i].pri) k--; // 寻找第一个小于当前元素的节点x
        if(k != 0)//如果栈中还有元素
        {
            tr[i].fat = stk[k-1]; //当前点的father变为x
            tr[stk[k-1]].son[1] = i;//当前节点插入成为x的右子节点
        }
        if(k != top)/*如果有element曾经出栈,那么需要将出栈的最后一个变成当前点的左
            子节点,因为出栈的所有element是一条链,只需要将最小的那个元素重新连接
            到树上就把整条链都连接上了*/
        {
            tr[stk[k]].fat = i; //出栈的最后一个的father变成当前节点
            tr[i].son[0] = stk[k];//当前节点的左节点变成最后一个出栈的节点
        }
        stk[k++] = i; // 右链的长度也因为当前点的插入而变成(当前点插入位置的深度+1)
        top = k;
    }
    return stk[0];//插入结束时右链的栈底的元素就是根
}
int main()
{
    int n=4000000;
    {
        int a , b;
        tr[0].init(0,0,0,0);
        for(int i = 1 ; i <= n ; i++)
        {
            a=rand();b=rand();
            //scanf("%d%d",&a,&b);
            tr[i].init(a,b,0,i);
        }
        sort(tr + 1, tr + 1 + n);
        root = car_build(n);
    }
    return 0;
}


LCA

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <complex>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <list>
#define Swap(a,b) {a=a^b;b=b^a;a=a^b;}
#define INF 0x3f3f3f3f
#define INFll 0x3f3f3f3f3f3f3f3fll
using namespace std;
class Graph{
	public:
	vector<vector<int> >edge;
	int vertices;
	private:
	struct ques{
		int snum,lca,tar;
		ques(){
			snum=0;lca=0;tar=0;
		}
		ques(int _num,int _tar):snum(_num),tar(_tar){}
	};
	vector<int>parent;
	vector<int>vis;
	vector<list<ques> >query;
	vector<int>ans;
	public:
	Graph(){
		edge.clear();parent.clear();vis.clear();query.clear();ans.clear();vertices=0;
	}
	Graph(int n):vertices(n){
		edge.clear();parent.clear();vis.clear();query.clear();ans.clear();vertices=n;
		edge.resize(n+1);
	}
	void resize(int n){
		vertices=n;edge.clear();edge.resize(n+1);
	}
	void build(){
		/** you need to edit it
			input:
	 			edge[][]
		*/ 
		for(int i=0;i<vertices-1;++i){
			int a,b;
			scanf("%d%d",&a,&b);
			edge[a].push_back(b);
			edge[b].push_back(a);
		}
	}
	private:
	int root(int x){
		int ans=x,tmp;
		while(parent[ans]!=ans) ans=parent[ans];
		while(x!=ans){
			tmp=x;
			x=parent[x];
			parent[tmp]=ans;
		}
		return ans;
	}
	void Tarjan_dfs(int curpos,int fa){
		int aim;
		for(int i=0;i<(int)edge[curpos].size();++i){
			aim=edge[curpos][i];
			if(aim==fa) continue;
			Tarjan_dfs(aim,curpos);
			parent[aim]=curpos;
			vis[aim]=1;
		}
		for(list<ques>::iterator it=query[curpos].begin();it!=query[curpos].end();++it){
			aim=it->tar;
			if(vis[aim]){
				ans[it->snum]=root(aim);
			}
		}
		query[curpos].clear();
	}
	public:
	void Tarjan(int query_num,int rt=1){
		parent.resize(vertices+1); for(int i=0;i<=vertices;++i) parent[i]=i;
		vis.resize(vertices+1,0);
		query.clear();query.resize(vertices+1);
		ans.resize(query_num);
		for(int i=0;i<query_num;++i){
			int a,b;
			scanf("%d%d",&a,&b);
			if(a==b){
				ans[i]=a;
			}else{
				query[a].push_back(ques(i,b));
				query[b].push_back(ques(i,a));
			}
			
		}
		Tarjan_dfs(rt,0);
	}
	void showAns(){
		//you need to edit it
		for(int i=0;i<(int)ans.size();++i) printf("%d\n",ans[i]);
	}
};
int main(){
	int n,m,rot;
	scanf("%d%d%d",&n,&m,&rot);
	Graph g(n);
	g.build();
	g.Tarjan(m,rot);
	g.showAns();
	return 0;
}

树状数组

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <list>
#define INF 0x3f3f3f3f
#define INFll 0x3f3f3f3f3f3f3f3fll
using namespace std;
template <typename _type_>
struct TreeArray1{	//单点修改、区间查询
	_type_ *_BinIndexTree;		//Binaray Indexed Tree 树状数组 
	int _n;						//长度 1~n
	TreeArray1(){
		_BinIndexTree=NULL;_n=0;
	}
	TreeArray1(int n){
		_n=n;
		_BinIndexTree=(_type_ *)calloc(2*_n,sizeof(_type_));
	}
	TreeArray1(_type_ *arr,int n){
		_n=n;
		_BinIndexTree=(_type_ *)calloc(2*_n,sizeof(_type_));
		for(int i=1;i<=n;++i){
			add(i,arr[i]);
		}
	}
	/*
	int lowbit(int x){	
			//x'father=x+lowbit(x)
			//x'child=x-lowbit(x)
		return x&(-x);
	}*/
	void build(int n){	//正常数组 	单点修改、区间查询 
		_n=n;
		_BinIndexTree=new _type_[2*n];
		memset(_BinIndexTree,0,sizeof(_BinIndexTree));
		long long tmp;
		for(int i=1;i<=n;++i){
			scanf("%lld",&tmp);
			add(i,(_type_)tmp);
		}
	}
	void add(int pos,_type_ x){	//tree[pos]+=x	单点修改 
		while(pos<=_n){
			_BinIndexTree[pos]+=x;
			pos+=(pos&-pos);
		}
	}
	private: _type_ sum(int pos){	//sum[1~pos] 区间查询
		_type_ res=0;
		while(pos){
			res+=_BinIndexTree[pos];
			pos-=(pos&-pos);
		}
		return res;
	}
	public: _type_ sum(int left,int right){		//sum[left~right] 区间查询
		return sum(right)-sum(left-1);
	}
	void show(){
		for(int i=1;i<=_n;++i){
			printf("%d ",_BinIndexTree[i]);
		}
	}
};

template <typename _type_>
struct TreeArray2{	//区间修改、单点查询 
	_type_ *_BinIndexTree;		//Binaray Indexed Tree 树状数组 
	int _n;						//长度 1~n
	TreeArray2(){
		_BinIndexTree=NULL;_n=0;
	}
	TreeArray2(int n){
		_n=n;
		_BinIndexTree=(_type_ *)calloc(2*_n,sizeof(_type_));
	}
	TreeArray2(_type_ *arr,int n){
		_n=n;
		_BinIndexTree=(_type_ *)calloc(2*_n,sizeof(_type_));
		for(int i=1;i<=n;++i){
			add(i,arr[i]);
		}
	}
	void build(int n){	//差分数组   区间修改、单点查询 
		_n=n;
		_BinIndexTree=new _type_[2*n];
		memset(_BinIndexTree,0,sizeof(_BinIndexTree));
		long long pre=0,tmp;
		for(int i=1;i<=n;++i){
			scanf("%lld",&tmp);
			add(i,(_type_)tmp-pre);
			pre=tmp;
		}
	}
	private: void add(int pos,_type_ x){	//tree[pos]+=x
		while(pos<=_n){
			_BinIndexTree[pos]+=x;
			pos+=(pos&-pos);
		}
	}
	public: void add(int left,int right,_type_ x){	//tree[left~right]+=x  区间修改 
		return add(left,x),add(right+1,-x);
	}
	_type_ sum(int pos){	//sum[1~pos] 单点查询
		_type_ res=0;
		while(pos){
			res+=_BinIndexTree[pos];
			pos-=(pos&-pos);
		}
		return res;
	}
	_type_ operator [](int pos){		//单点查询 
		return sum(pos);
	}
	void show(){
		for(int i=1;i<=_n;++i){
			printf("%d ",_BinIndexTree[i]);
		}
	}
};


template <typename _type_>
struct TreeArray{	//区间修改、区间查询 
	_type_ *_BinIndexTree1;
	_type_ *_BinIndexTree2;
	int _n;						//长度 1~n
	TreeArray(){
		_BinIndexTree1=_BinIndexTree2=NULL;_n=0;
	}
	TreeArray(int n){
		_n=n;
		_BinIndexTree1=(_type_ *)calloc(2*_n,sizeof(_type_));
		_BinIndexTree2=(_type_ *)calloc(2*_n,sizeof(_type_));
	}
	TreeArray(_type_ *arr,int n){
		_n=n;
		_BinIndexTree1=(_type_ *)calloc(2*_n,sizeof(_type_));
		_BinIndexTree2=(_type_ *)calloc(2*_n,sizeof(_type_));
		for(int i=1;i<=n;++i){
			add(i,arr[i]);
		}
	}
	void build(int n){	//双数组   区间修改、区间查询 
		_n=n;
		_BinIndexTree1=(_type_ *)calloc(2*_n,sizeof(_type_));
		_BinIndexTree2=(_type_ *)calloc(2*_n,sizeof(_type_));
		long long tmp,pre=0; 
		for(int i=1;i<=n;++i){
			scanf("%lld",&tmp);
			add(i,(_type_)(tmp-pre));
			pre=tmp;
		}
	}
	private: void add(int pos,_type_ x){	//tree[pos]+=x
		for(int i=pos;i<=_n;i+=(i&-i)){
			_BinIndexTree1[i]+=x;
			_BinIndexTree2[i]+=x*(pos-1);
		}
	}
	public: void add(int left,int right,_type_ x){	//tree[left~right]+=x  区间修改 
		return add(left,x),add(right+1,-x);
	}
	private: _type_ sum(int pos){	//sum[1~pos]
		_type_ res=0;
		for(int i=pos;i;i-=(i&-i)){
			res+=(_BinIndexTree1[i]*pos-_BinIndexTree2[i]);
		}
		return res;
	}
	public: _type_ sum(int left,int right){		//区间查询 
		return sum(right)-sum(left-1);
	}
	void show(){
		for(int i=1;i<=_n;++i){
			printf("%d ",_BinIndexTree1[i]);
		}putchar('\n');
		for(int i=1;i<=_n;++i){
			printf("%d ",_BinIndexTree2[i]);
		}
	}
};

int main(){
	int n,q;
	scanf("%d%d",&n,&q);
	TreeArray<long long>itr;
	itr.build(n);
	itr.show();cout<<endl;
	while(q--){
		int opt,a,b,k;
		scanf("%d",&opt);
		if(opt==1){
			scanf("%d%d%d",&a,&b,&k);
			itr.add(a,b,k);
		}else{
			scanf("%d%d",&a,&b);
			printf("%lld\n",itr.sum(a,b));
		}
		itr.show();cout<<endl;
	}
    return 0;
}

dijkstra

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <list>
#define INF 0x3f3f3f3f
using namespace std;
struct edge{
	int to;
	long long val;
	edge(int _v,long long _w):to(_v),val(_w){}
	bool operator < (const edge &p)const{
		return to<p.to||(to==p.to&&val<p.val);
	}
};
int n,m;	//n:vertices' number   m:edges' number
vector<vector<edge> >edges;
long long *dis;
typedef pair<long long,int> P;	//first:distance second:to No.   for heap in dijkstra
void dijkstra(int start=1){
	priority_queue<P,vector<P>,greater<P> > ique;
	dis=new long long [n+1];
	memset(dis,0x3f,(n+1)*sizeof(long long));
	dis[start]=0;
	ique.push(P(0,start));
	while(!ique.empty()){
		P p=ique.top();
		ique.pop();
		int v=p.second;
		if(dis[v]<p.first)continue;
		for(int i=0;i<edges[v].size();++i){
			edge e=edges[v][i];
			if(dis[e.to]>dis[v]+e.val){
				dis[e.to]=dis[v]+e.val;
				ique.push(P(dis[e.to],e.to));
			}
		}
	}
}
void showEdges(){
	cout<<endl;
	for(int i=1;i<=n;++i){
		for(int j=0;j<edges[i].size();++j){
			printf("%d %d %d\n",i,edges[i][j].to,edges[i][j].val);
		}
	}
}

void showDis(){
	for(int i=1;i<n;++i){
		printf("%lld ",dis[i]);
	}printf("%lld\n",dis[n]);
}
int main(){
	int start;
	scanf("%d%d%d",&n,&m,&start);
	//make graph
	int v1,v2;long long wei;
	edges.resize(n+1);
	for(int i=0;i<m;++i){
		scanf("%d%d%lld",&v1,&v2,&wei);
		edges[v1].push_back(edge(v2,wei));
		//edges[v2].push_back(edge(v1,wei));	//undirected
	}
	for(int i=1;i<=n;++i){
		sort(edges[i].begin(),edges[i].end());
	}
	
	dijkstra(start);
	
	showDis();
	
    return 0;
}

基于一定标准的图及图上MST、割点、强连通、缩点、LCA

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <list>
#include <bitset>
#define INF 0x3f3f3f3f
using namespace std;
//第一次使用请注意修改 TODO 部分函数
class UnionFindSet{
	public:
	int *_par;
	long long *_num;
	UnionFindSet(int n=10000){
		_par=NULL;_num=NULL;
		build(n);
	}
	void build(int n=10000){
		if(_par) free(_par);
		_par=new int[n+1];
		if(_num) free(_num);
		_num=new long long[n+1];
		for(int i=0;i<=n;++i) _par[i]=i,_num[i]=1;
	}
	int root(int x){
		int r=x,tmp;
		while(r!=_par[r]) r=_par[r];
		while(x!=r){
			tmp=_par[x];_par[x]=r;x=tmp;
		}
		return x;
	}
	bool Union(int a,int b){
		int ap=root(a),bp=root(b);
		if(ap==bp) return false;
		if(ap<bp){		//ap<-bp
			_par[bp]=ap;
			_num[ap]+=_num[bp];
		}else{
			_par[ap]=bp;
			_num[bp]+=_num[ap];
		}
		return true;
	}
	void clear(){
		free(_par);free(_num);_par=NULL;_num=NULL;build();
	}
};


template <typename _type_=long long>//recommmand long long or double
class Graph{
	private:
	struct node_que{//for priority_queue in function "span_prim","span_kurskal"
		int from,to;
		_type_ val;
		node_que(int _from,int _to,_type_ _w):from(_from),to(_to),val(_w){}
		bool operator >(const node_que &p)const{
			return val>p.val;
		}
	};
	struct edge{//for edges
		int to;
		_type_ val;
		edge(int _v,_type_ _w=(_type_)1):to(_v),val(_w){}
	};
	public:
	//[1,ver_num] (begin from 1/点的编号从1开始)
	int ver_num,edge_num;	//vertices' number   edges' number
	vector<vector<edge> >edges;
	vector<vector<edge> >spantree;
	bool undirected;	//undirected graph/无向图
	vector<int>cutver;	//cut vertex/articulation point/割点
	vector<vector<int> >compress_edges;		//compressed-edges/经过缩点后的图,
	vector<vector<int> >contain;			//compressed-point contains points/缩点后各点包含的/强连通图内的点
	//scg_sum  compressed-points number/缩点后的点数
	//color	   各点对应的颜色
	/****************基础函数部分*****************/
	Graph(){
		initial();
	}
	public:void initial(){
		ver_num=0;edge_num=0;
		edges.clear();
		spantree.clear();
		undirected=true;
		cutver.clear();
		_dfn=_low=_instack=istack=color=NULL;_cnt=scg_sum=ttop=0;
		compress_edges.clear();
	}
	public:void buildGraph(int n,int m){
		//TODO
		//you should edit here, avoid vertice 0
		undirected=true;
		ver_num=n;edge_num=m;
		edges.resize(n+1);
		for(int i=0;i<m;++i){
			int a,b;double w;
			scanf("%d%d",&a,&b);
			//scanf("%lf",&w);
			w=0;
			//a,b>=1 attention
			edges[a].push_back(edge(b,(_type_)w));
			if(undirected) edges[b].push_back(edge(a,(_type_)w));
		}
	}
	public:void buildTree(int n,int m){
		//TODO
		//you should edit here, avoid vertice 0
		ver_num=n;edge_num=m;
		edges.resize(n+1);
		for(int i=0;i<m;++i){
			int a,b;double w;
			scanf("%d%d%lf",&a,&b,&w);
			//a,b>=1 attention
			edges[a].push_back(edge(b,(_type_)w));
			if(undirected)edges[b].push_back(edge(a,(_type_)w));
			spantree[a].push_back(edge(b,(_type_)w));
			if(undirected)spantree[b].push_back(edge(a,(_type_)w));
		}
	}
	/****************基础函数部分结束*****************/
	/****************生成树部分*****************/
	public:_type_ span_prim(int start=1){//mlogn
		//return sum of edges or -1 when graph isn't connnected, "spantree" will span with points connected to point "start"
		if(ver_num==0) return (_type_)-1;
		_type_ res=0;
		spantree.clear();
		spantree.resize(ver_num+1);
		priority_queue<node_que,vector<node_que>,greater<node_que> > ique;
		int *vis=(int*)calloc(ver_num+1,sizeof(int));
		_type_ *dis=(_type_*)malloc((ver_num+1)*sizeof(_type_));
		memset(dis,0x3f,(ver_num+1)*sizeof(_type_));
		ique.push(node_que(0,start,(_type_)0));
		while(!ique.empty()){
			node_que tmp=ique.top();ique.pop();
			if(vis[tmp.to]) continue;
			int u=tmp.to;
			res+=tmp.val;
			if(u!=start){
				spantree[tmp.from].push_back(edge(u,tmp.val));
				if(undirected)spantree[u].push_back(edge(tmp.from,tmp.val));
			}
			vis[u]=1;
			for(int i=0;i<edges[u].size();++i){
				if(!vis[edges[u][i].to]){
					ique.push(node_que(u,edges[u][i].to,edges[u][i].val));
					dis[edges[u][i].to]=min(dis[edges[u][i].to],edges[u][i].val);
				}
			}
		}
		for(int i=1;i<=ver_num;++i) if(!vis[i]) return (_type_)-1;
		return res;
	}
	public:_type_ span_kurskal(){//mlogm
		//return sum of edges or -1 when graph isn't connnected, "spantree" will be nothing
		if(ver_num==0) return (_type_)-1;
		_type_ res=0;
		spantree.clear();
		spantree.resize(ver_num+1);
		priority_queue<node_que,vector<node_que>,greater<node_que> > ique;
		int *vis=(int*)calloc(ver_num+1,sizeof(int));int left=ver_num;
		UnionFindSet iset(ver_num);
		for(int i=1;i<=ver_num;++i){
			for(int j=0;j<edges[i].size();++j){
				ique.push(node_que(i,edges[i][j].to,edges[i][j].val));
			}
		}
		while(!ique.empty()){
			node_que tmp=ique.top();ique.pop();
			if(iset.Union(tmp.from,tmp.to)){
				res+=tmp.val;
				spantree[tmp.from].push_back(edge(tmp.to,tmp.val));
				if(undirected)spantree[tmp.to].push_back(edge(tmp.from,tmp.val));
				if(!vis[tmp.from]) vis[tmp.from]=1,--left;
				if(!vis[tmp.to]) vis[tmp.to]=1,--left;
			}
		}
		if(left){spantree.clear();return (_type_)-1;}
		return res;
	}
	/*****************生成树部分结束*****************/
	//割点与连通图共用变量:
		private:int *_dfn,*_low,_cnt;
	/*****************割点部分*****************/
	private:void dfs_cutver(int from,int cur){//O(n+m)
		_dfn[cur]=_low[cur]=++_cnt;
		int kids=0,flag=0;
		for(int i=0;i<edges[cur].size();++i){
			int nx=edges[cur][i].to;
			if(!_dfn[nx]){
				++kids;
				dfs_cutver(cur,nx);
				_low[cur]=min(_low[cur],_low[nx]);
				if(from==cur&&kids==2&&!flag) cutver.push_back(cur),flag=1;
				else if(from!=cur&&_low[nx]>=_dfn[cur]&&!flag) cutver.push_back(cur),flag=1;
			}
			else if(from!=nx){
				_low[cur]=min(_low[cur],_dfn[nx]);
			}
		}
	}
	public:int getCutVertex(){//O(n+m)
		//return cut vertexs' number
		if(ver_num==0) return -1;
		_dfn=(int*)calloc(ver_num+1,sizeof(int));_low=(int*)calloc(ver_num+1,sizeof(int));_cnt=0;
		for(int i=1;i<=ver_num;++i) if(!_dfn[i]) dfs_cutver(i,i);
		free(_dfn);free(_low);_cnt=0;_dfn=_low=NULL;
		sort(cutver.begin(),cutver.begin()+cutver.size());
		return cutver.size();
	}
	/*****************割点部分结束*****************/
	/*****************强连通图部分*****************/
	private:int *_instack;int *istack;int ttop;
	public:int *color;int scg_sum;
	private:void dfs_scg(int cur){//O(n+m)
		_dfn[cur]=_low[cur]=++_cnt;
		_instack[cur]=1;
		istack[ttop++]=cur;
		for(int i=0;i<edges[cur].size();++i){
			int nx=edges[cur][i].to;
			if(!_dfn[nx]){
				dfs_scg(nx);
				_low[cur]=min(_low[cur],_low[nx]);
			}else if(_instack[nx]){
				_low[cur]=min(_low[cur],_dfn[nx]);
			}
		}
		if(_dfn[cur]==_low[cur]){
			++scg_sum;
			while(istack[ttop]!=cur){
				color[istack[--ttop]]=scg_sum;
				_instack[ttop]=0;
				contain[scg_sum].push_back(_instack[ttop]);
			}
			color[cur]=scg_sum;
			_instack[cur]=0;
			--ttop;
			contain[scg_sum].push_back(cur);
		}
	}
	public:int getSConnectedG(){//O(n+m)
		//return points' number of Strongly Connected Graph
		if(ver_num==0) return -1;
		_dfn=(int*)calloc(ver_num+1,sizeof(int));_low=(int*)calloc(ver_num+1,sizeof(int));_cnt=0;
		_instack=(int*)calloc(ver_num+1,sizeof(int));scg_sum=0;istack=(int*)calloc(ver_num+1,sizeof(int));ttop=0;
		if(color)free(color),color=NULL;
		color=(int*)calloc(ver_num+1,sizeof(int));	//color\scg_sum 不释放

		contain.resize(ver_num+1);
		for(int i=1;i<=ver_num;++i) if(!_dfn[i]) dfs_scg(i);
		contain.resize(scg_sum+1);

		free(_dfn);free(_low);_cnt=0;_dfn=_low=NULL;
		free(istack);ttop=0;istack=NULL;
		free(_instack);_instack=NULL;
		return scg_sum;
	}
	/*****************强连通图部分结束*****************/
	/*****************缩点部分*************************/
	public:bool getCompressedG(){//O(n+m)
		if(scg_sum<=0||color<=0) if(getSConnectedG()<=0) return false;
		compress_edges.resize(scg_sum+1);
		for(int i=1;i<=ver_num;++i){
			for(int j=0;j<edges[i].size();++j){
				int nxt=edges[i][j].to;
				if(color[i]!=color[nxt]){
					compress_edges[color[i]].push_back(color[nxt]);
				}
			}
		}
		vector<int>::iterator new_end;
		for(int i=1;i<=scg_sum;++i){
			sort(compress_edges[i].begin(),compress_edges[i].end());
			new_end=unique(compress_edges[i].begin(),compress_edges[i].end());
			compress_edges[i].erase(new_end,compress_edges[i].end());
		}
		return true;
	}

	/*****************缩点部分结束*****************/
	/*****************LCA部分**********************/


	/*****************LCA部分结束******************/
};
int main(){
	Graph<long long>mst;
	int n,m;
	scanf("%d%d",&n,&m);
	mst.buildGraph(n,m);
	/*
	cout<<"MST all edges:"<<endl;
	for(int i=0;i<mst.spantree.size();++i){
		for(int j=0;j<mst.spantree[i].size();++j){
			cout<<i<<' '<<mst.spantree[i][j].to<<' '<<mst.spantree[i][j].val<<endl;
		}
	}
	for(int i=0;i<mst.edges.size();++i){
		for(int j=0;j<mst.edges[i].size();++j){
			cout<<i<<' '<<mst.edges[i][j].to<<' '<<mst.edges[i][j].val<<endl;
		}
	}*/
	mst.getCompressedG();
	for(int i=1;i<=mst.scg_sum;++i){
		cout<<i<<": ";
		for(int j=0;j<mst.compress_edges[i].size();++j){
			cout<<mst.compress_edges[i][j]<<' ';
		}cout<<endl;
	}
    return 0;
}

LCS、LIS

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
#include <complex>
#include <algorithm>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <list>
#define Swap(a,b) {a=a^b;b=b^a;a=a^b;}
#define INF 0x3f3f3f3f
#define INFll 0x3f3f3f3f3f3f3f3fll
using namespace std;
class Graph{
	public:
	vector<vector<int> >edge;
	int vertices;
	private:
	struct ques{
		int snum,lca,tar;
		ques(){
			snum=0;lca=0;tar=0;
		}
		ques(int _num,int _tar):snum(_num),tar(_tar){}
	};
	vector<int>parent;
	vector<int>vis;
	vector<list<ques> >query;
	vector<int>ans;
	public:
	Graph(){
		edge.clear();parent.clear();vis.clear();query.clear();ans.clear();vertices=0;
	}
	Graph(int n):vertices(n){
		edge.clear();parent.clear();vis.clear();query.clear();ans.clear();vertices=n;
		edge.resize(n+1);
	}
	void resize(int n){
		vertices=n;edge.clear();edge.resize(n+1);
	}
	void build(){
		/** you need to edit it
			input:
	 			edge[][]
		*/ 
		for(int i=0;i<vertices-1;++i){
			int a,b;
			scanf("%d%d",&a,&b);
			edge[a].push_back(b);
			edge[b].push_back(a);
		}
	}
	private:
	int root(int x){
		int ans=x,tmp;
		while(parent[ans]!=ans) ans=parent[ans];
		while(x!=ans){
			tmp=x;
			x=parent[x];
			parent[tmp]=ans;
		}
		return ans;
	}
	void Tarjan_dfs(int curpos,int fa){
		int aim;
		for(int i=0;i<(int)edge[curpos].size();++i){
			aim=edge[curpos][i];
			if(aim==fa) continue;
			Tarjan_dfs(aim,curpos);
			parent[aim]=curpos;
			vis[aim]=1;
		}
		for(list<ques>::iterator it=query[curpos].begin();it!=query[curpos].end();++it){
			aim=it->tar;
			if(vis[aim]){
				ans[it->snum]=root(aim);
			}
		}
		query[curpos].clear();
	}
	public:
	void Tarjan(int query_num,int rt=1){
		parent.resize(vertices+1); for(int i=0;i<=vertices;++i) parent[i]=i;
		vis.resize(vertices+1,0);
		query.clear();query.resize(vertices+1);
		ans.resize(query_num);
		for(int i=0;i<query_num;++i){
			int a,b;
			scanf("%d%d",&a,&b);
			if(a==b){
				ans[i]=a;
			}else{
				query[a].push_back(ques(i,b));
				query[b].push_back(ques(i,a));
			}
			
		}
		Tarjan_dfs(rt,0);
	}
	void showAns(){
		//you need to edit it
		for(int i=0;i<(int)ans.size();++i) printf("%d\n",ans[i]);
	}
};
int main(){
	int n,m,rot;
	scanf("%d%d%d",&n,&m,&rot);
	Graph g(n);
	g.build();
	g.Tarjan(m,rot);
	g.showAns();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值