1. 程式人生 > 其它 >docker容器基本原理及安裝

docker容器基本原理及安裝

從上週五開始學縮點,今天終於把程式碼敲過了,再次做一個總結(有好多問題需要總結)。
概念:
縮點:在一張有向圖中,將圖中的強連通分量縮成一個點。
連通分量:一個點集,是的點集中的點兩兩之間可以互相抵達。
強連通分量:這個點集中無法再加入一個新的點。
思路:
1.從一個未搜過的點開始,將這個點標記為正在搜的點,並用另一陣列記錄這個點為第幾個被搜到的點(dfn),把這個點放入棧中。
2.搜這個點能到達的所有的點,並用一個數組記錄它能到的所有的點中dfn最小的一個(low)(能到的所有的點包括未搜的和正在搜的)。
3.在搜完後判斷如果這個點的dfn和low相等說明從棧頂到這個元素屬於同一個強連通分量,並把它們從這個棧中刪掉,將這些點標記為搜完的點。
我在學縮點的期間遇到的一些問題:
1.

從點1開始,先查2,再查3,再查4,又查到1,返回到1,接著查5,返回來dfn[1]是等於low[1]的,所以這是一個強連通分量,但是點1,2,3,4是一個強連通分量,不包括5。
解釋:判斷點1前就已經判斷了點5,而且已經將點5自己判斷為一個強連通分量,出棧了,所以記錄時會將點1,2,3,4記錄為一個強連通分量,點5記錄為一個強連通分量。
2.

我原來的時候一直在一個點搜完後將它標記為搜完,而不是在它出棧時標記,就一直錯。
解釋:根據上面這個圖,點1,2,3,4顯然是一個強連通分量,但是如果在一個點搜完後就立刻將它標記為搜完,點4就不會搜點3了,這樣就會將點4自己標記為一個強連通分量所以要在它出棧時再將它標記為搜完。
下面是程式碼:

點選檢視程式碼
#include<iostream>
using namespace std;
int n,m;
int a[10010];
int head[10010],tot;
int shead[10010],stot;
struct node{
	int to;
	int nxt;
}edge[100010],sedge[100010];
void build(int u,int v){
	edge[++tot].to=v;
	edge[tot].nxt=head[u];
	head[u]=tot;
}
void addedge(int u,int v){
	sedge[++stot].to=v;
	sedge[stot].nxt=shead[u];
	shead[u]=stot;
}
int dfn[10010],low[10010],cnt;
int zhen[100010],top;
int dian[10010],shu;
int dui[10010];
int ru[10010];
int vis[10010];
void dfs(int u){
	low[u]=dfn[u]=++cnt;
	zhen[++top]=u;
	vis[u]=1;
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].to;
		if(dfn[v]==0){
			dfs(v);
			low[u]=min(low[v],low[u]);
		}
		else if(vis[v]==1)low[u]=min(low[u],low[v]);
	}
	if(low[u]==dfn[u]){
		shu++;
		while(zhen[top]!=u){
			vis[zhen[top]]=0;
			dian[shu]+=a[zhen[top]];
			dui[zhen[top]]=shu;
			top--;
		}
		top--;
		dui[u]=shu;
		dian[shu]+=a[u];
		vis[u]=0;
	}
}
int maxn;
int f[10010];
void tuopu(int u){
	for(int i=shead[u];i;i=sedge[i].nxt){
		int v=sedge[i].to;
		if(f[u]+dian[v]>f[v]){
			f[v]=f[u]+dian[v];
			maxn=max(maxn,f[v]);
			tuopu(v);
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=m;i++){
		int u,v;
		cin>>u>>v;
		build(u,v);
	}
	for(int i=1;i<=n;i++){
		if(dfn[i]==0){
			dfs(i);
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=head[i];j;j=edge[j].nxt){
			int v=edge[j].to;
			if(dui[v]!=dui[i]){
				addedge(dui[i],dui[v]);
				ru[dui[v]]++;
			}
		}
	}
	for(int i=1;i<=shu;i++){
		if(ru[i]==0){
			f[i]=dian[i];
			maxn=max(f[i],maxn);
			tuopu(i);
		}
	}
	cout<<maxn;
	return 0;
}
題目可以看洛谷P3387。