SPFA algorithm optimization (title)

review:

SPFA optimization algorithm has two SLF and LLL:

SLF : the Label Small First strategy, the node is set to join j, head of the queue elements i, if dist (j) <dist (i ), insert the first team will j, otherwise insert team tail.

    To deque <int> 

LLL : Large the Label Last policy (not used), the first element is provided team i, the average of all the values in the queue as dist x, if dist (i)> x i will be inserted into the tail, to find the next element, until i found that certain dist (i) <= x, then the relaxation operation performs i. SLF can speed 15 ~ 20%; SLF + LLL can be increased by about 50%. SPFA time efficiency of the algorithm is not very stable in practical applications, in order to avoid the worst case, usually more stable efficiency of Dijkstra's algorithm. Personally I feel that the average per request optimization LLL, very good, for simplicity, we can use between c ++ STL priority queue inside to optimize the SLF.

 

 

Through a subject (not all optimization)

1504: [Example 1] Word Rings

A string as an edge, at both ends of the character as a character node, as the length of weight . Binary enumeration answer , finally being SPFA brush ring, as long as there exists a positive ring to it.
Each word treated as an edge, by the beginning of the two-letter pointing to the end of the two letters, the right side for the length of the word. Seeking the former problem into a minimum ratio ring. (Ha and minimum ratio spanning tree like)
may be utilized bipartite + spfa answer to resolve arbitration ring. Point up to 26 * 26, while a maximum sentence 1e5.dfs version spfa ring is fast. .
If there ring string, output No solution, otherwise, the output of the average length of the longest string ring.

#include <the iostream> 
#include <CString> 
#include <the cmath> 
#include <algorithm> 
#include <Stack> 
#include <cstdio> 
#include <Queue> 
#include <Map> 
#include <Vector> 
#include <SET> 
STD namespace the using; 
const int = 1E5 + MAXN 10; 
const int = INF 0x3FFFFFFF; 
const = EPS Double-1E. 4; 
typedef Long Long LL; 
// a string as an edge, at both ends of the character as a character node, as the length of weight. Binary enumeration answer, finally being SPFA brush ring, as long as there exists a positive ring to it. 
// each word treated as an edge, by the beginning of the two-letter pointing to the end of the two letters, the right side for the length of the word. The original problem into seeking an optimal ratio ring, 
// you can use half the answer ring + spfa sentenced to resolve. Point up to 26 * 26, while a maximum sentence 1e5.dfs version spfa ring is fast. . 
// This question still do not understand 
// I know, I do not read this topic woman 
// If there ring string, output No solution, otherwise the output of the average length of the longest string in the ring. 

 
char aa [1010];
int head [MAXN], VIS [MAXN]; 
Double DIS [MAXN]; 
int n-, CNT; 
struct Node { 
	int to, Next, DIS; 
} ED [MAXN * 10]; 
void the Add (int A, int B, int C) { 
	ED [CNT ++] = B .to; 
	ED [CNT] .dis = C; 
	ED [CNT] head .next = [A]; 
	head [A] = CNT; 
} 
int JS (A char, char B) { 
	return (A-'A ') 26+ * (B-'A') +. 1; // add to. 1 
} 
BOOL SPFA (int X, Double MID) { 
	VIS [X] =. 1; 
	for (int head = I [X]; I; I = ED [I] .next) { 
		int ED = T [I] .to; 
		IF (DIS [X] + ED [I] .dis-MID> DIS [T]) {//! ! ! ! Because the maximum thing is to 
			DIS [t] = DIS [X] + ED [I] .dis-MID; 
			IF (VIS [t] || SPFA (t, MID)) {// if t has accessed later or can be return 1, then there is a ring, it can return a 
				VIS [X] = 0; 
				return 1;
			}
		}
	}
	vis[x]=0;
	return 0; 
}
bool judge(double mid){
	memset(dis,0,sizeof(dis));
	for(int i=1;i<=26*26;i++){   //枚举!!!!!!点最多有26*26个,枚举以每一个点为起点 
		if(spfa(i,mid)) return 1;
	}
	return 0;
}
int main(){
	while(scanf("%d",&n)&&n){
		memset(vis,0,sizeof(vis));
		memset(head,0,sizeof(head));
		for(int i=0;i<n;i++){
			scanf("%s",aa);
			int len=strlen(aa);
			add(js(aa[0],aa[1]),js(aa[len-2],aa[len-1]),len); //建边 
		}
		double mid,left=0,right=1000;  //二分 
		while(right-left>=eps){
			mid=(left+right)/2;
			if(judge(mid)){
				left=mid;
			}
			else right=mid;
		}
		if(left==0) printf("No solution\n");
		else printf("%.2lf\n",left);
	}
return 0;
}  

1505: [Example 2] amphiregulin path

Description [title]

From the original title: BalticOI 2002

Today's road pricing has developed rapidly. Road density increases, so choose the best path is a very real problem. The city is a two-way road, each road has a fixed travel time and expense required to pay.

After the road is a continuous path composed. The total time is the roads and travel time, the total cost is the cost of the roads paid the sum. The faster a path, or the lower the cost, the better the path. Strictly speaking, if one path faster than any other path, but do not need to pay more, it is better. In turn, understood as such. If a path is not better than a certain path, the path is called a minimum path.

Such a path of least there may be more than one, or simply path does not exist.

Question: reading network, the total number of the smallest path calculation. The same time the cost of a minimum of two paths only count as one. You just output the minimum number of different types of path.

[Enter]

The first line has four integers, the total number of cities n, the total number of road m, start and end city s, e;

The next m lines each describe information of a road, comprising four integers, two endpoints p, r, C costs, and time T;

There may be multiple paths connection between the two cities.

[Output]

Only a number representing the total number of the smallest path.

Obviously, this is a shortest subject
but there are two states
so we can not directly open the array
should a state presence in the ancestral tree, the other for the index
because we know that a path is optimal only when it's a case another indicator is greater than the optimal path and its another indicator of that path is less than (or another path is not the optimal solution)
thus be obtained, the optimal solution set of two indicators are rising and declining

// where each road there are two key values, you can think of a one-dimensional backpack, dp [i] [j] represents the minimum time when the i-th city to spend money j;

#include <the iostream> 
#include <CString> 
#include <the cmath> 
#include <algorithm> 
#include <Stack> 
#include <cstdio> 
#include <Queue> 
#include <Map> 
#include <Vector> 
#include <SET> 
namespace std a using; 
const int MAXN = 110; 
const int INF = 0x3f3f3f3f; 
typedef Long Long LL; 
/ * 
obviously, this is a shortest subject 
but there are two states 
so we can not directly open the array 
should exist a state tree Zu, the other index is 
because we know that a path to the optimal case only when it is an indicator of the optimal path is larger than the other and it's smaller than the other indicators that path (or another path is not the optimal solution a) 
thus be obtained, the optimal solution set of two indicators, respectively upward and downward trend 
* / 
// wherein each path has two key values, can be associated knapsack, dp [i] [j] when the minimum time that the first i j city to spend money; 
int head [MAXN]; 
int VIS [MAXN] [MAXN * 100];
LL f [maxn] [maxn * 100]; // f [i] [j] to the representative of the cost of the i-th time point when the minimum J 
int CNT, n-, m, S, E; 
struct Node { 
	int to , Next, Ti, Wei; 
} ED [610]; 
struct TT { 
	int POS, Money; 
}; 
void the Add (int X, int Y, int Z, int D) { 
	CNT ++; 
	ED [CNT] .to = Y; 
	ED [CNT] head .next = [X]; 
	ED [CNT] .TI = Z; 
	ED [CNT] D = .wei; 
	head [X] = CNT; 
} 

void SPFA (int ST) { 
	TT TEMP; 
	TEMP. ST = POS; 
	temp.money = 0; 
	Queue <TT> Q; 
	q.push (TEMP); 
	VIS [ST] [0] =. 1; 
	F [ST] [0] = 0; 
	the while (q.empty (! )) { 
		TT q.front OP = (); 
		q.pop (); 
		VIS [op.pos] [op.money] = 0;
		IF (op.money> = (. 1-n-) * 100) Continue; 
		// phrase! ! ! ! Because the topic that time, money, less than 10 
		for (int I = head [op.pos]; I; I = ED [I] .next) { 
			int = V ED [I] .to; 
			IF (F [V] [op.money + ed [i] .wei ]> f [op.pos] [op.money] + ed [i] .ti) {// If they longer than the time point 
				f [v] [op. ED + Money [I] .wei] = F [op.pos] [op.money] + ED [I] .TI; 
				IF (! VIS [V] [op.money ED + [I] .wei]) { 
					VIS [V] [op.money ED + [I] .wei] =. 1; 
					TT NE; 
					ne.money op.money + = ED [I] .wei; ne.pos = V; 
					q.push (NE); 
				} 
			} 
		} 
	} 
} 
int main () { 
	Scanf ( "% D% D% D% D", & n-, & m, & S, & E); 
	int A, B, C, D; 
	for (int I = 0; I < m; I ++) { 
		Scanf ( "% D%% D D D%", & A, & B, & C, & D);
		add(b,a,c,d);
	}
	memset(f,0x3f,sizeof(f));
	spfa(s);
	int mintime=INF,ans=0;
	for(int i=0;i<=n*100;i++){
		if(f[e][i]==INF||f[e][i]>=mintime) continue;
		mintime=f[e][i];
		ans++;
	}
	printf("%d\n",ans);
return 0;
}

1506: Minimum Cycle

Obviously a fraction of planning topic if we can find a negative figure in the ring, it shows ans can use real numbers continue to shrink to half

Compare with the word rings like, but this is the minimum required

#include <the iostream> 
#include <CString> 
#include <the cmath> 
#include <algorithm> 
#include <Stack> 
#include <cstdio> 
#include <Queue> 
#include <Map> 
#include <Vector> 
#include <SET> 
a using namespace std; 
const int MAXN = 3010; 
const int MAXM = 1E4 + 10; 
const int INF = 0x3FFFFFFF; 
const int eps = 1E-9; 
typedef Long Long LL; 
// obviously a fraction of the planning of the subject if we are able to FIG find a negative ring, it shows ans can continue to refine the use of real-half to 
int n-, m; 
int head [MAXN]; 
struct Node { 
	int to, Next; 
	Double DIS; 
} ED [MAXM]; 
int VIS [MAXN ], CNT; 
Double DIS [MAXN]; 
void ADDE (A int, int B,double c){
	cnt++;
	ed[cnt].to=b;
	ed[cnt].next=head[a];
	ed[cnt].dis=c;
	head[a]=cnt;
}
bool dfs(int now,double mid){
	vis[now]=1;
	
	for(int i=head[now];i!=0;i=ed[i].next){
		int t=ed[i].to;
		if(dis[t]>dis[now]+ed[i].dis-mid){
			dis[t]=dis[now]+ed[i].dis-mid;
			if(vis[t]) return 1;
			else if(dfs(t,mid)) return 1;
		}
	}
	vis[now]=0;
	return 0;
}
bool ju(double mid){
	memset(vis,0,sizeof(vis));
	memset(dis,0,sizeof(dis));
	for(int i=1;i<=n;i++){
		if(dfs(i,mid)) return 1;
	}
	return 0;
}
int main(){
	scanf("%d %d",&n,&m);
	int x,y;
	double z;
	double l=1e8,r=-1e8,mid;
	for(int i=0;i<m;i++){
		scanf("%d %d %lf",&x,&y,&z);
		adde(x,y,z);  //有向图 
		l=min(l,z);
		r=max(r,z);
	}
	
	while(r-l>eps){
		mid=(l+r)/2.0;
		if(ju(mid)) r=mid;
		else l=mid;
	}
	printf("%.8lf\n",l);
return 0;
}

1507: Wormhole Wormholes

This question is of the essence see through: negated ring, to get the negative side of the wormhole, and a team entering the number n exists over
so like spfa

#include <the iostream> 
#include <CString> 
#include <the cmath> 
#include <algorithm> 
#include <Stack> 
#include <cstdio> 
#include <Queue> 
#include <Map> 
#include <Vector> 
#include <SET> 
STD namespace the using; 
const int MAXN = 1010; 
const int = INF 0x3FFFFFFF; 
typedef Long Long LL; 
// see-through nature of this question: negated ring, to get the negative side of the wormhole, then entering a number of teams there is more than n 
// so spfa like 
struct Node { 
	int to, Next, T; 
} ED [10005]; 
int head [2501]; 
int DIS [510], NUM [510], VIS [510]; 
int F , n-, m, W, CNT; 
void ADDE (A int, int B, int C) { 
	ED [CNT ++] = B .to; 
	ED [CNT] head .next = [A]; 
	ED [CNT]. t = c;
	head[a]=cnt;
}
bool spfa(){
	queue<int> q;
	for(int i=1;i<=n;i++) dis[i]=INF;
	dis[1]=1;
	vis[1]=1;
	num[1]++;
	q.push(1);
	while(!q.empty()){
		int op=q.front();
		q.pop();
		vis[op]=0;
		for(int i=head[op];i;i=ed[i].next){
			int tt=ed[i].to;
			if(dis[tt]>dis[op]+ed[i].t){
				dis[tt]=dis[op]+ed[i].t;
				if(!vis[tt]){
					vis[tt]=1;
					num[tt]++;
					q.push(tt);
					if(num[tt]==n) return 1;
				}
			}
		}
	}
	return 0;
}
int main(){
	scanf("%d",&f);
	while(f--){
		scanf("%d %d %d",&n,&m,&w);
		memset(vis,0,sizeof(vis));
		memset(num,0,sizeof(num));
		memset(head,0,sizeof(head));
		cnt=0;  //这个记得清零 
		for(int i=1;i<=m;i++){
			int x,y,z;
			scanf("%d %d %d",&x,&y,&z);
			adde(x,y,z);
			adde(y,x,z);
		}
		for(int i=1;i<=w;i++){
			int x,y,z;
			scanf("%d %d %d",&x,&y,&z);
			adde(x,y,-z);   //边权为负的 
		}
		if(spfa()) printf("YES\n");
		else printf("NO\n");
	}
	
	
	
return 0;
}

1508:Easy SSSP

A given input data has N nodes, M weighted directed graph edges. I ask you to write a program to determine the presence or absence of negative cycles have directed graph. If starting from a point along a path, back to himself, and through which the right edge and less than 0, say this road is a negative cycles.

If the negative cycles, of only one line of output 1; negative cycles, if not present, then find a point S to the shortest length of each point. Conventions: S is the distance S 0, if S is not connected to this point, the output NoPath.

congratulations! ! ! Finally used the optimized friends ~

#include <the iostream> 
#include <CString> 
#include <the cmath> 
#include <algorithm> 
#include <Stack> 
#include <cstdio> 
#include <Queue> 
#include <Map> 
#include <Vector> 
#include <SET> 
STD namespace the using; 
const int MAXN = 1010; 
const int = 1E5 + 10 MAXM; 
const int = INF 0x3FFFFFFF; 
typedef Long Long LL; 
LL n-, m, S, CNT; 
LL head [MAXN]; 
// loop negative weight may there is no starting point and together !!! 
// you can open a Boolean array, if this point the team had, put it labeled as true. SPFA run again after the enum ever entered the team's point pitted again on the line . 
struct {Node 
	LL to, DIS, Next; 
} ED [MAXM]; 
LL DIS [MAXN]; 
int VIS [MAXN]; // no stored into the team had 
LL ans [maxn];// final result, save the starting point, 
LL NUM [MAXN];
int isok[maxn]; //保存有没有访问过 
void add(LL a,LL b,LL c){
	ed[++cnt].to=b;
	ed[cnt].next=head[a];
	ed[cnt].dis=c;
	head[a]=cnt;
}
deque<LL> q;
int spfa(LL st){
	for(int i=1;i<=n;i++) dis[i]=INF;
	for(int i=1;i<=cnt;i++) num[i]=0;  //每次都要清一次0 
	dis[st]=0;
	if(!q.empty()) q.pop_front();  //清空 
	//queue<int> q;
	q.push_back(st);
	while(!q.empty()){
		LL op=q.front();
		q.pop_front();
		vis[op]=0;
		for(int i=head[op];i;i=ed[i].next){
			LL tt=ed[i].to;
			if(dis[tt]>dis[op]+ed[i].dis){
				dis[tt]=dis[op]+ed[i].dis;
				if(!vis[tt]){
					isok[tt]=1;
					num[tt]++;
					if(num[tt]>n) return -1;
					if(q.empty()) q.push_back(tt);  //没办法,只有一种放法 
					else{
						if(dis[tt]<dis[q.front()]) q.push_front(tt);  //放前面 
						else q.push_back(tt);  //放后面 
					}
					vis[tt]=1;
				}
			}
		}
	}
	return 1;
}
int main(){
	scanf("%lld %lld %lld",&n,&m,&s);
	LL x,y,z;
	for(int i=1;i<=m;i++){
		scanf("%lld %lld %lld",&x,&y,&z);
		add(x,y,z);
	}
	int ok=spfa(s);
	if(ok==-1){
		printf("-1");
		return 0;
	}
	for(int i=1;i<=n;i++) ans[i]=dis[i];  //!!!!在这里保存答案 
	
		for(int i=1;i<=n;i++){
			if(!isok[i]){
				ok=spfa(i);
				if(ok==-1){
					printf("-1");
					return 0;
				}
			} 
		}
		for(int i=1;i<=n;i++){
			if(dis[i]==INF) printf("NoPath\n");
			else printf("%lld\n",ans[i]);
		}
return 0;
}


//错了两个点
#include<bits/stdc++.h>
#define inf 0x6fffffff
#define ll long long
#define maxn 1005
using namespace std;
struct node{
    ll v,w,nxt;
}edge[maxn*100];
ll n,m,cnt[maxn],dis[maxn],k=1,s,head[maxn],ans[maxn];
bool vis[maxn],done[maxn];
inline void adde(ll u,ll v,ll w)
{
    edge[k].v=v;
    edge[k].w=w;
    edge[k].nxt=head[u];
    head[u]=k++;
}
deque<ll> q;
inline bool SPFA(ll s)
{
    for(int i=1;i<=n;i++) cnt[i]=0; 
    if(!q.empty()) q.pop_front();
    for(int i=1;i<maxn;i++) dis[i]=inf;
    dis[s]=0;
    q.push_back(s);
    while(!q.empty())
    {
        ll u=q.front();q.pop_front();
        vis[u]=0;
        for(int i=head[u];i;i=edge[i].nxt)
        {
            ll v=edge[i].v;
            if(dis[v]>dis[u]+edge[i].w)
            {
                dis[v]=dis[u]+edge[i].w;
                if(!vis[v])
                {
                    done[v]=1;
                    cnt[v]++;
                    if(cnt[v]>n) return 0;
                    if(q.empty()) q.push_back(v);
                    else
                    {
                        if(dis[v]<dis[q.front()]) q.push_front(v);
                        else q.push_back(v);
                    }
                    vis[v]=1;
                }
            }
        }
    }
    return 1;
}
int main()
{
    scanf("%lld%lld%lld",&n,&m,&s);
    for(int i=1;i<=m;i++)
    {
        ll t1,t2,t3;
        scanf("%lld%lld%lld",&t1,&t2,&t3);
        adde(t1,t2,t3);
    }
    int haha=SPFA(s);
    if(!haha) 
    {
        printf("-1");
        return 0;
    }
    for(int i=1;i<=n;i++) ans[i]=dis[i];
    for(int i=1;i<=n;i++)
    {
        if(!done[i])
        {
            haha=SPFA(i);
            if(!haha)
            {
                printf("-1");
                return 0;
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(ans[i]<inf) printf("%lld\n",ans[i]);
        else printf("NoPath\n");
    }
    return 0;
} 

  

 

Guess you like

Origin www.cnblogs.com/shirlybaby/p/12617243.html