圖論刷題整理


圖論習題整理

求先序排列

需要知道樹的遍歷方法,分別前中后序,代表着先訪問根節點,左子樹,右子樹,或是左中右,或是左右中

現在給同一棵樹的中后兩個序列,求前序,

首先清楚這樣的性質:

1.對於某個樹(無論是子樹還是本體,只要是棵完整的樹就行),其前序遍歷序列的第一個節點肯定是它的根,就是對於節點,其位於的層數越淺越靠后

對於后序遍歷也類似,只是相反

2.中序遍歷雖然看起來很亂,啥用沒有,但是它在划分子樹(是左子樹還是右子樹)上有着不可或缺的作用,畢竟對於一個數的中序序列,一旦找到根節點,其左子樹和右子樹就非常好確定了

3.因為無論哪種遍歷,都是挨個按照子樹的順序去遍歷的,所以子樹的序列在總序列里面一定是連續的,不存在穿插的情況

那么這就好辦了,遞歸處理規定區間的序列就好

先將后序序列中最后一位取出,在中序序列中進行查找,然后規定中序序列的左右子樹,也就是下一步的目標,進行遞歸處理

同時,我們注意到中序遍歷和后序遍歷的子樹區間並不對應,所以要同時處理兩個序列需要處理的區間,中序好說,關鍵是后序

我們發現對於后序序列,其構成一定為:(左子樹)+(右子樹)+(根節點)

就是一定是這樣有序的

那么只要處理出區間長度(就是子樹大小,當然左右需要分開的),差不多這題就結了,

記得我們在處理中序序列時找的根節點嗎?就用它的下標來作區間處理

這里的區間表示有點考驗思維,建議自己推(不推反正下面也有代碼

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
char tar1[10];
char tar2[10];
int len;
inline int find(const char &x){
	for(int i=1;i<=len;i++)
		if(tar1[i]==x) return i;
}
inline void search(int l1,int r1,int l2,int r2){
	printf("%c",tar2[r2]);
	int t=find(tar2[r2]);
	if(t>l1) search(l1,t-1,l2,r2+t-r1-1);
	if(t<r1) search(t+1,r1,l2+t-l1,r2-1);
}
int main(){
	scanf("%s",tar1+1);
	scanf("%s",tar2+1);
	len=strlen(tar1+1);
	search(1,len,1,len);
	return 0;
}

沒有與最短路及其算法相關的圖論整理博客不是好博客(本來就不是

蟲洞Wormholes

題目翻譯:

給了一堆數據范圍(題目中的小路不會耗10000秒什么的也是數據范圍啦...)

然后問你有沒有負環

(我興致沖沖想寫最短路你給我看這個?

看到題,看到環,不要什么時候都想着tarjan...tarjan只是存強連通分量的算法,雖然環也可以,但是用於找負環...有SPFA為什么不用呢?

SPFA基於廣搜BFS,深搜DFS當然可以過但是對於那道負環模板題就會被卡掉

為什么SPFA(或者Bellman-Ford)會被負環卡掉?

因為SPFA見到可以更新到很小,就一定會進行更新和入隊(准備下一步松弛)

那么負環正是可以"無限縮小"的這么一種東西,就這樣,SPFA在無限的更優方案中死掉了

每一個點只要入隊超過n-1次,就說明有負環,因為每個店最多被其他每個點各松弛一次,多了就是在里面繞起來了,用它判負環就是了

代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
int t;
int n,m;
struct Ed{
	int to,nxt,dis;
}ed[50005];
int head[20005];
bool vis[20005];
int tms[20005];
int ednum;
inline void add(const int &from,const int &to,const int &dis){
	ed[++ednum].to=to;
	ed[ednum].dis=dis;
	ed[ednum].nxt=head[from];
	head[from]=ednum;
}
int dis[20005];
queue<int> q;
inline bool spfa(){
	memset(dis,0x3f,sizeof dis);
	memset(vis,0,sizeof vis);
	memset(tms,0,sizeof tms);
	dis[1]=0;
	vis[1]=1;
	tms[1]++;
	q.push(1);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u];i;i=ed[i].nxt){
			if(dis[ed[i].to]>dis[u]+ed[i].dis){
				dis[ed[i].to]=dis[u]+ed[i].dis;
				if(!vis[ed[i].to]){
					q.push(ed[i].to);
					vis[ed[i].to]=1;
					tms[ed[i].to]++;
					if(tms[ed[i].to]>=n)
						return 1;
				}
			}
		}
	}
	return 0;
}
int main(){
	scanf("%d",&t);
	while(t--){
		memset(ed,0,sizeof ed);
		memset(head,0,sizeof head);
		ednum=0;
		int w;
		scanf("%d%d%d",&n,&m,&w);
		for(int i=1;i<=m;i++){
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			add(a,b,c);
			add(b,a,c);
		}
		for(int i=1;i<=w;i++){
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			add(a,b,-c);
		}
		bool ok=spfa();
		if(ok) printf("YES\n");
		else printf("NO\n");
	}return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM