我觉得他整理的有一些乱,我都改成插入代码了,看的顺眼一些

转载自http://blog.csdn.net/juststeps/article/details/8772755

下面的都是原文:

最短路径 之 SPFA算法

http://hi.baidu.com/southhill/item/ab26a342590a5aae60d7b967

求最短路径的算法有许多种,除了排序外,恐怕是OI界中解决同一类问题算法最多的了。最熟悉的无疑是Dijkstra,接着是Bellman-Ford,它们都可以求出由一个源点向其他各点的最短路径;如果我们想要求出每一对顶点之间的最短路径的话,还可以用Floyd-Warshall。

SPFA是这篇日志要写的一种算法,它的性能非常好,代码实现也并不复杂。特别是当图的规模大,用邻接矩阵存不下的时候,用SPFA则可以很方便地面对临接表。每个人都写过广搜,SPFA的实现和广搜非常相似。

如何求得最短路径的长度值?

首先说明,SPFA是一种单源最短路径算法,所以以下所说的“某点的最短路径长度”,指的是“某点到源点的最短路径长度”。

我们记源点为S,由源点到达点i的“当前最短路径”为D[i],开始时将所有D[i]初始化为无穷大,D[S]则初始化为0。算法所要做的,就是在运行过程中,不断尝试减小D[]数组的元素,最终将其中每一个元素减小到实际的最短路径。

过程中,我们要维护一个队列,开始时将源点置于队首,然后反复进行这样的操作,直到队列为空:

(1)从队首取出一个结点u,扫描所有由u结点可以一步到达的结点,具体的扫描过程,随存储方式的不同而不同;

(2)一旦发现有这样一个结点,记为v,满足D[v] > D[u] + w(u, v),则将D[v]的值减小,减小到和D[u] + w(u, v)相等。其中,w(u, v)为图中的边u-v的长度,由于u-v必相邻,所以这个长度一定已知(不然我们得到的也不叫一个完整的图);这种操作叫做松弛。

引用内容
松弛操作的原理是著名的定理:“三角形两边之和大于第三边”,在信息学中我们叫它三角不等式。所谓对i,j进行松弛,就是判定是否d[j]>d[i]+w[i,j],如果该式成立则将d[j]减小到d[i]+w[i,j],否则不动。

(3)上一步中,我们认为我们“改进了”结点v的最短路径,结点v的当前路径长度D[v]相比于以前减小了一些,于是,与v相连的一些结点的路径长度可能会相应地减小。注意,是可能,而不是一定。但即使如此,我们仍然要将v加入到队列中等待处理,以保证这些结点的路径值在算法结束时被降至最优。当然,如果连接至v的边较多,算法运行中,结点v的路径长度可能会多次被改进,如果我们因此而将v加入队列多次,后续的工作无疑是冗余的。这样,就需要我们维护一个bool数组Inqueue[],来记录每一个结点是否已经在队列中。我们仅将尚未加入队列的点加入队列。

算法能否结束?

对于不存在负权回路的图来说,上述算法是一定会结束的。因为算法在反复优化各个最短路径长度,总有一个时刻会进入“无法再优化”的局面,此时一旦队列读空,算法就结束了。然而,如果图中存在一条权值为负的回路,就糟糕了,算法会在其上反复运行,通过“绕圈”来无休止地试图减小某些相关点的最短路径值。假如我们不能保证图中没有负权回路,一种“结束条件”是必要的。这种结束条件是什么呢?

思考Bellman-Ford算法,它是如何结束的?显然,最朴素的Bellman-Ford算法不管循环过程中发生了什么,一概要循环|V|-1遍才肯结束。凭直觉我们可以感到,SPFA算法“更聪明一些”,就是说我们可以猜测,假如在SPFA中,一个点进入队列——或者说一个点被处理——超过了|V|次,那么就可以断定图中存在负权回路了。

最短路径本身怎么输出?

在一幅图中,我们仅仅知道结点A到结点E的最短路径长度是73,有时候意义不大。这附图如果是地图的模型的话,在算出最短路径长度后,我们总要说明“怎么走”才算真正解决了问题。如何在计算过程中记录下来最短路径是怎么走的,并在最后将它输出呢?

Path[]数组,Path[i]表示从S到i的最短路径中,结点i之前的结点的编号。注意,是“之前”,不是“之后”。最短路径算法的核心思想成为“松弛”,原理是三角形不等式,方法是上文已经提及的。我们只需要在借助结点u对结点v进行松弛的同时,标记下Path[v] = u,记录的工作就完成了。

输出时可能会遇到一点难处,我们记的是每个点“前面的”点是什么,输出却要从最前面往最后面输,这不好办。其实很好办,见如下递归方法:

程序代码
void PrintPath(int k){
    if( Path[k] ) PrintPath(Path[k]);
    fout<<k<<' ';
}

SPFA的代码怎么写?

我写了邻接表和邻接矩阵两种,两者想像起来是那么的不同,算法的思路上实在区别不大,只是用不同方式诠释“扫描”的过程而已。只给出SPFA的单个函数,我不觉得很容易看懂,但是我仍然把两个程序的SPFA函数放在下面。在日志的结尾处,有一个完整版文件下载。贴程序,首先是邻接表的:

程序代码

void SPFA(){
for(int i=; i<=gv; i++)
Dist[i] = ;
Dist[S] = ;
int closed = , open = ;
queue[] = S;
Inqueue[S] = true;
do{
closed++;
node *tmp = connect[queue[closed]];
Inqueue[queue[closed]] = false;
while(tmp != NULL){
if( Dist[tmp->key] > Dist[queue[closed]] + tmp->w ){
Dist[tmp->key] = Dist[queue[closed]] + tmp->w;
Path[tmp->key] = queue[closed];
if( !Inqueue[tmp->key] ){
Inqueue[tmp->key] = true;
open++;
queue[open] = tmp->key;
}
}
tmp = tmp->next;
}
}while(closed < open);
}

然后是邻接矩阵的:

程序代码

void SPFA(){
for( int i=; i<=gv; i++){
Dist[i] = ;
for( int j=; j<=gv; j++)
if( !Graph[i][j] && i!=j) Graph[i][j] = ;
}
int closed = , open = ;
queue[] = S;
Dist[S] = ;
do{
closed++;
int u = queue[closed];
Inqueue[u] = false;
for(int i=; i<=gv; i++)
if ( Dist[i] > Dist[u] + Graph[u][i] ){
Dist[i] = Dist[u] + Graph[u][i];
Path[i] = u;
if( !Inqueue[i] ){
Inqueue[i] = true;
open++;
queue[open] = i;
}
}
}while(closed < open);
}

spfa算法 Easy sssp 收藏 
输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的带权有向图. 
要求你写一个程序, 判断这个有向图中是否存在负权回路. 如果从一个点沿着某条路径出发, 又回到了自己, 而且所经过的边上的权和小于0, 就说这条路是一个负权回路.
如果存在负权回路, 只输出一行-1;
如果不存在负权回路, 再求出一个点S(1 <= S <= N)到每个点的最短路的长度. 约定: S到S的距离为0, 如果S与这个点不连通, 则输出NoPath.

INPUT:
第一行: 点数N(2 <= N <= 1,000), 边数M(M <= 100,000), 源点S(1 <= S <= N);
以下M行, 每行三个整数a, b, c表示点a, b(1 <= a, b <= N)之间连有一条边, 权值为c(-1,000,000 <= c <= 1,000,000)

OUTPUT:
如果存在负权环, 只输出一行-1, 否则按以下格式输出
共N行, 第i行描述S点到点i的最短路: 
如果S与i不连通, 输出NoPath;
如果i = S, 输出0;
其他情况输出S到i的最短路的长度

INPUT:
6 8 1
1 3 4
1 2 6
3 4 -7
6 4 2
2 4 5
3 6 3
4 5 1
3 5 4

OUTPUT:
0
6
4
-3
-2
7

注意:
题目说的不是很清楚,给出的图不一定是完全联通图,有些是断开的几个图,所以在判断的源点是否有环以外还要分别对不同的点进行spfa呀。再进行分别的判断和输出。

有几个优化:
1.可以先判断是否有负权自环,有则直接输出-1
2.在枚举的过程中,当这个顶点的最短路(d[i])<0时,有负权回路,输出-1.

【参考程序】:

 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
long queue[],a[],psum[],dis[],l[][],cost[][];
long n,m,s,i,j;
bool hash[],bk;
void spfa(int s)
{
int head,tail,start,now,i;
for (i=;i<=n;i++)
{
dis[i]=0xfffffff;
psum[i]=;
hash[i]=false;
}
head=tail=;hash[s]=true;
psum[s]=;dis[s]=;queue[]=s;
while (head<=tail)
{
start=queue[(head-)%n+];
hash[start]=true;
for (i=;i<=l[start][];i++)
{
now=l[start][i];
if (dis[now]>dis[start]+cost[start][now])
{
dis[now]=dis[start]+cost[start][now];
if (!hash[now])
{
hash[now]=true;
tail++;
queue[(tail-)%n+]=now;
psum[now]++;
if (psum[now]>n)
{//记录每个点进队的次数(判断环的关键}
bk=false;
return;
}
}
}
}
head++;
hash[start]=false;
if (dis[s]<)
{//判断环的一个优化
bk=false;
return;
}
}
}
void output()
{
bk=true;
spfa(s);
if (!bk)
{
printf("-1\n");
return;
}
memcpy(a,dis,sizeof(long)*(n+));
for (i=;i<=n;i++)
if (a[i]==0xfffffff)
{
bk=true;
spfa(i);
if (!bk)
{
printf("-1\n");
return;
}
}
for (i=;i<=n;i++)
if (a[i]==0xfffffff) printf("NoPath\n");
else printf("%d\n",a[i]);
}
void input()
{
scanf("%d%d%d",&n,&m,&s);
for (i=;i<=n;i++)
for (j=;j<=n;j++)
if (i==j) cost[i][j]=;
else cost[i][j]=0xfffffff;
memset(l,,sizeof(l));
int x,y,c;
for (i=;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&c);
if (c<cost[x][y])
{
cost[x][y]=c;
l[x][]++;
l[x][l[x][]]=y;
}
}
}
int main()
{
input();
output();
system("pause");
return ;
}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/bobcowwocb/archive/2009/09/14/4550188.aspx

2009年07月24日 星期五 15:10
SPFA算法模版+邻接表实现 
SPFA即shotest path faster algorithm,由意思就可以看出该算法效率比较高。

其实SPFA就是bellman-ford算法的一个优化。

具体做法是用一个队列保存待松弛的点,然后对于每个出队的点依次遍历每个与他有边相邻的点(用邻接表效率较高),如果该点可以松弛并且队列中没有该点则将它加入队列中,如此迭代直到队列为空。

据说平均效率是O(E),可见对边稀疏的图用此算法效果是相当可观的。

若要判负环路,则记录一个点的入队次数,若超过边数,则有负权环。

 #include <iostream>
#include <queue>
using namespace std; const long MAXN=;
const long lmax=0x7FFFFFFF; typedef struct
{
long v;
long next;
long cost;
}Edge; Edge e[MAXN];
long p[MAXN];
long Dis[MAXN];
bool vist[MAXN]; queue<long> q; long m,n;//点,边
void init()
{
long i;
long eid=; memset(vist,,sizeof(vist));
memset(p,-,sizeof(p));
fill(Dis,Dis+MAXN,lmax); while (!q.empty())
{
q.pop();
} for (i=;i<n;++i)
{
long from,to,cost;
scanf("%ld %ld %ld",&from,&to,&cost); e[eid].next=p[from];
e[eid].v=to;
e[eid].cost=cost;
p[from]=eid++; //以下适用于无向图
swap(from,to); e[eid].next=p[from];
e[eid].v=to;
e[eid].cost=cost;
p[from]=eid++; }
} void print(long End)
{
//若为lmax 则不可达
printf("%ld\n",Dis[End]);
} void SPF()
{ init(); long Start,End;
scanf("%ld %ld",&Start,&End);
Dis[Start]=;
vist[Start]=true;
q.push(Start); while (!q.empty())
{
long t=q.front();
q.pop();
vist[t]=false;
long j;
for (j=p[t];j!=-;j=e[j].next)
{
long w=e[j].cost;
if (w+Dis[t]<Dis[e[j].v])
{
Dis[e[j].v]=w+Dis[t];
if (!vist[e[j].v])
{
vist[e[j].v]=true;
q.push(e[j].v);
}
}
}
} print(End); } int main()
{
while (scanf("%ld %ld",&m,&n)!=EOF)
{
SPF();
}
return ;
}

一、Bellman-Ford算法

最优性原理

它是最优性原理的直接应用,算法基于以下事实:

l          如果最短路存在,则每个顶点最多经过一次,因此不超过n-1条边;

l          长度为k的路由长度为k-1的路加一条边得到;

l          由最优性原理,只需依次考虑长度为1,2,…,k-1的最短路。

适用条件&范围

l          单源最短路径(从源点s到其它所有顶点v);

l          有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图);

l          边权可正可负(如有负权回路输出错误提示);

l          差分约束系统(需要首先构造约束图,构造不等式时>=表示求最小值, 作为最长路,<=表示求最大值, 作为最短路。<=构图时, 有负环说明无解;求不出最短路(为Inf)为任意解。>=构图时类似)。

算法描述

l          对每条边进行|V|-1次Relax操作;

l          如果存在(u,v)∈E使得dis[u]+w<dis[v],则存在负权回路;否则dis[v]即为s到v的最短距离,pre[v]为前驱。

时空复杂度

for i:=1 to |V|-1 do

for 每条边(u,v)∈E do   Relax(u,v,w);

for每条边(u,v)∈E do

if dis[u]+w<dis[v] Then Exit(False)

算法时间复杂度O(VE)。因为算法简单,适用范围又广,虽然复杂度稍高,仍不失为一个很实用的算法。

改进和优化   如果循环n-1次以前已经发现不存在紧边则可以立即终止; Yen氏改进(不降低渐进复杂度);SPFA算法

二、             SPFA算法

算法简介 
SPFA(Shortest Path Faster Algorithm)是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算。 它可以在O(kE)的时间复杂度内求出源点到其他所有点的最短路径,可以处理负边。

算法流程 
SPFA对Bellman-Ford算法优化的关键之处在于意识到:只有那些在前一遍松弛中改变了距离估计值的点,才可能引起他们的邻接点的距离估计值的 改变。因此,算法大致流程是用一个队列来进行维护,即用一个先进先出的队列来存放被成功松弛的顶点。初始时,源点s入队。当队列不为空时,取出队首顶点, 对它的邻接点进行松弛。如果某个邻接点松弛成功,且该邻接点不在队列中,则将其入队。经过有限次的松弛操作后,队列将为空,算法结束。SPFA算法的实 现,需要用到一个先进先出的队列 queue 和一个指示顶点是否在队列中的标记数组mark。为了方便查找某个顶点的邻接点,图采用临界表存储。

算法代码 
Procedure SPFA;Begin             initialize-single-source(G,s);             initialize-queue(Q);             enqueue(Q,s);             while not empty(Q) do begin                u:=dequeue(Q);                for each v∈adj[u] do begin                   tmp:=d[v]; relax(u,v);                   if (tmp<>d[v]) and (not v in Q) then enqueue(v);                   end;                end;End;负环处理
   需要特别注意的是:仅当图不存在负权回路时,SPFA能正常工作。如果图存在负权回路,由于负权回路上的顶点无法收敛,总有顶点在入队和出队往返,队列无法为空,这种情况下SPFA无法正常结束。

判断负权回路的方案很多,世间流传最广、比较容易实现并且高效的方法的是记录每个结点进队次数,超过|V|次表示有负权。

三、             学以致用

POJ 1201 Intervals 差分约束系统

设S(i)为 0..i-1 中在最终序列中的的整数个数。则约束条件如下:

S(b)-S(a) >= c

0 <= S(i+1) - S(i) <= 1 <==> S(i+1)-S(i) >= 0;

S(i)-S(i+1) >= -1

注意本题要求的是最小值, 而按照>=号建图后发现图中有负环, 怎么办呢?

其实很简单, 本题求的不是最短路, 而是最长路! Bellman_ford即可!

POJ 1275 Cashier Employment 出纳员的雇佣

黑书上有详细讲解

POJ 1364 King 差分约束系统

这个题目构图之后, 只需要用bellman_ford判断是否有负圈.

构图方法:

首先进行转换:a[j]+...+a[j+m] = a[1]+...a[j+m] - (a[1]+...+a[j-1]) = sum[j+m] -

sum[j-1] >(<) ki. 差分约束只能全部是<=或者(>=).

第二步转换: sum[j+m]-sum[j-1] <= ki-1 或者 sum[j-1]-sum[j+m] <= -ki-1.

约束图构造好后就是简单的Bellman-Ford了!

POJ 1716 Integer Intervals 是1201的简单版本, 贪心算法能够得到更好的效果.

POJ 2983 Is the Information Reliable?

差分约束题, 处理一下等号的情况, 然后普通的Bellman_ford

POJ 3159 Candies 最短路径

Bellman-Ford超时, Dijkstra算法可以高效解决, SPFA(队列)居然超时...SPFA修改为堆栈实现就过了.

POJ 3169 Layout 差分约束

Bellman-Ford 和 SPFA 实现均可

POJ 3259 Wormholes 判断负权回路

TOJ 2976 Path 单纯的最短路径 可练习SPFA

ZOJ 3033 Board Games 我做的第一道Bellman-Ford题目

首先,DFS判断可达性,不可达直接输出infinity结束,可达,bellman-ford判断是否存在负环,存在输出infinity,否则,输出最短距离。

SPFA算法模版+邻接表实现 
SPFA即shotest path faster algorithm,由意思就可以看出该算法效率比较高。

其实SPFA就是bellman-ford算法的一个优化。

具体做法是用一个队列保存待松弛的点,然后对于每个出队的点依次遍历每个与他有边相邻的点(用邻接表效率较高),如果该点可以松弛并且队列中没有该点则将它加入队列中,如此迭代直到队列为空。

据说平均效率是O(E),可见对边稀疏的图用此算法效果是相当可观的。

若要判负环路,则记录一个点的入队次数,若超过边数,则有负权环。

 #include <iostream>
#include <queue>
using namespace std; const long MAXN=;
const long lmax=0x7FFFFFFF; typedef struct
{
long v;
long next;
long cost;
}Edge; Edge e[MAXN];
long p[MAXN];
long Dis[MAXN];
bool vist[MAXN]; queue<long> q; long m,n;//点,边
void init()
{
long i;
long eid=; memset(vist,,sizeof(vist));
memset(p,-,sizeof(p));
fill(Dis,Dis+MAXN,lmax); while (!q.empty())
{
q.pop();
} for (i=;i<n;++i)
{
long from,to,cost;
scanf("%ld %ld %ld",&from,&to,&cost); e[eid].next=p[from];
e[eid].v=to;
e[eid].cost=cost;
p[from]=eid++; //以下适用于无向图
swap(from,to); e[eid].next=p[from];
e[eid].v=to;
e[eid].cost=cost;
p[from]=eid++; }
} void print(long End)
{
//若为lmax 则不可达
printf("%ld\n",Dis[End]);
} void SPF()
{ init(); long Start,End;
scanf("%ld %ld",&Start,&End);
Dis[Start]=;
vist[Start]=true;
q.push(Start); while (!q.empty())
{
long t=q.front();
q.pop();
vist[t]=false;
long j;
for (j=p[t];j!=-;j=e[j].next)
{
long w=e[j].cost;
if (w+Dis[t]<Dis[e[j].v])
{
Dis[e[j].v]=w+Dis[t];
if (!vist[e[j].v])
{
vist[e[j].v]=true;
q.push(e[j].v);
}
}
}
} print(End); } int main()
{
while (scanf("%ld %ld",&m,&n)!=EOF)
{
SPF();
}
return ;
}

POJ 1511-Invitation Cards(SPFA算法) 
今天终于用SPFA写出了第一个程序,感觉收获很大,从Dij到Floyed再到Bellmen,以及今天的SPFA,每一种算法背后都蕴藏着许多值得思考的地方。正因为研究了它们,才使得我的能力不断地获得了提高。
之前以为SPFA做为最短路问题最快的算法,想必代码定不好写,不过今天研究过才知道,SPFA的代码量远远不及Dij,这着实令人惊叹,原来最好的算法SPFA是如此的好写,呵呵 我想此算法在很大程度上可以完全代替之前的算法,以后再碰到最短路问题时,SPFA一定能成为首要的选择!
PS:由于是用邻接表来存储的,所以每次操作前要收回以前分配的内存,我尝试了收回和不收回两种方法,发现其实差别不大,如果纯粹是比赛的话,可能不收回反而会更好些(避免超时)。当然如果在实际应用中,应该切记内存的分配,否则软件可能会发生异常。

 //Coded by abilitytao
//Time:2009-04-10 22:49:58
#include<iostream>
#include<cmath>
#include<queue>
using namespace std;
#define MAX_NUM 1000000001
#define MAX_DOTNUM 1000001 int n,m;
queue<int>myqueue;
bool mark[MAX_DOTNUM];
__int64 dis[MAX_DOTNUM]; struct node
{ int v;
int w;
node *next;
}edge[MAX_DOTNUM];//此邻接表用于存储正向图 node reversed_edge[MAX_DOTNUM];//此逆邻接表用于存储逆向图 void initial(node edge[])//邻接表的初始化,里面封装了回收上一次操作所分配之内存的操作
{
int i;
node *p;
node *q;
for(i=;i<=n;i++)
{
p=&edge[i];
q=p->next;
while(q!=NULL)
{
p->next=q->next;
delete q;
q=p->next;
}
}
} void input_case()//每一个case的输入函数
{ int i;
for(i=;i<=m;i++)
{
node *p;
node *q;
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
/**/////////////////////////
p=&edge[a];
q=new node;
q->v=b;
q->w=c;
q->next=p->next;
p->next=q;
/**/////////////////////////
p=&reversed_edge[b];
q=new node;
q->v=a;
q->w=c;
q->next=p->next;
p->next=q;
}
} void spfa(node edge[])//SPFA部分
{ int i;
/**////////////////////////////////////////////////////////////////
memset(mark,false,sizeof(mark));
for(i=;i<=n;i++)
dis[i]=MAX_NUM;
while(myqueue.size()!=)
myqueue.pop();
/**////////////////////////////////////////////////////////////
dis[]=;
mark[]=true;
myqueue.push();
while(myqueue.size()!=)//如果队列不空,则进行松弛操作,直到队列空为止
{
int temp=myqueue.front();
myqueue.pop();
mark[temp]=false;
node *p;
for(p=edge[temp].next;p!=NULL;p=p->next)
{
if(dis[p->v]>dis[temp]+p->w)
{
dis[p->v]=dis[temp]+p->w;
if(mark[p->v]!=true)
{
myqueue.push(p->v);
mark[p->v]=true;
}
}
}
}
} int main()
{ int testcase;
int i,j;
__int64 sum;
scanf("%d",&testcase);
for(i=;i<=MAX_DOTNUM-;i++)
{
edge[i].v=i;
edge[i].w=;
edge[i].next=NULL;
}
for(i=;i<=MAX_DOTNUM-;i++)
{
reversed_edge[i].v=i;
reversed_edge[i].w=;
reversed_edge[i].next=NULL;
}
for(i=;i<=testcase;i++)
{
sum=;
scanf("%d%d",&n,&m);
initial(edge);
initial(reversed_edge);
input_case();
spfa(edge);
for(j=;j<=n;j++)
sum+=dis[j];
spfa(reversed_edge);
for(j=;j<=n;j++)
sum+=dis[j];
printf("%I64d\n",sum);
}
system("pause");
return ; }

觉得一篇讲SPFA还不错的文章的更多相关文章

  1. 上一篇括号配对让人联想起catalan数,顺便转载一篇归纳的还不错的文章

    转载请注明来自souldak,微博:@evagle 怎么样才是合法的组合? 只要每一时刻保证左括号的数目>=右括号的数目即可. 直接递归就行,每次递归加一个括号,左括号只要还有就能加,右括号要保 ...

  2. 关于Java集合框架,这篇讲的还算不错了,建议大家看看!

    集合框架 为什么要用集合而非数组: 虽然数组是保存一组对象最有效的方式,但是数组具有固定尺寸,但在写程序时并不知道将需要多少个对象.而集合能够自动地调整自己的尺寸. 打印数组时,必须使用Arrays. ...

  3. 一些LR的经验,讲的还不错

    https://blog.csdn.net/Dinosoft/article/details/50492309 记录一下.

  4. Java学到什么程度能找到一份还不错的工作

    我的读者里有很多 Java 新人,新人是指正在学 Java 的.以及工作时间不长的年轻人,他们经常问我一个问题: Java 学到什么程度才能找到一份还不错的工作? 今天我就从我自己面试新人的角度来回答 ...

  5. JS组件系列——再推荐一款好用的bootstrap-select组件,亲测还不错

    前言:之前分享过两篇bootstrap下拉框的组件:JS组件系列——两种bootstrap multiselect组件大比拼  和 JS组件系列——Bootstrap Select2组件使用小结 ,收 ...

  6. android studio还不错

    今天体验了哈 Android Studio,还不错同Elipse类似

  7. 【原创】PicUploader: 一个还不错的图床工具

    PicUploader PicUploader 是一个用php编写的图床工具,它能帮助你快速上传你的图片到云图床,并自动返回Markdown格式链接到剪贴板.配置完成后,要获取一个可用于markdow ...

  8. 最近在写h5的页面,发现有一款框架还不错给大家推荐一下

    wui 说一下自己写项目的体会吧,自我感觉wui还不错,能够让自己很快地把页面布局好,而且里面一些js效果也不用自己去手写jQuery代码很方便,下面让我们一起来认识一下wui这个框架吧 1,acco ...

  9. [daily][archlinux][game] 几个linux下还不错的游戏

    春节在家放松, 装了几个游戏在archlinux上,玩起来还不错. 假期结束开工了, 玩的时间也会比较少,准备删掉, 记录如下: 1. 0ad 即时战略类, 类似于冷兵器时代的红警. 画面还不错, 可 ...

随机推荐

  1. Tomcat web.xml配置参数详解

    Apache Tomcat Configuration Reference - The Context Containerhttps://tomcat.apache.org/tomcat-5.5-do ...

  2. linux pstree命令

    pstree命令可以使进程以tree的形式显示 pstree -ssystemd─┬─UVPHostd───6*[{UVPHostd}] ├─acpid ├─2*[agetty] ├─crond ├─ ...

  3. Kettle转换工具Windows版安装

    一.简介 Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行,绿色无需安装,数据抽取高效稳定. Kettle 中文名称叫水壶,该项目的主程序员MAT ...

  4. spring boot 获取bean

    在写测试用例的时候,如果是springboot的应该加上 springboot的标签: @SpringBootTest(classes = ApplicationLoader.class) @Acti ...

  5. 解决mybatis generator警告Cannot obtain primary key information from the database, generated objects may be incomplete

    使用 mybatis generator 生成pojo.dao.mapper时 经常出现 Cannot obtain primary key information from the database ...

  6. 转 Pycharm及python安装详细教程

    转 : http://blog.csdn.net/qq_29883591/article/details/52664478 首先我们来安装Python 1.首先进入网站下载:点击打开链接(或自己输入网 ...

  7. Lodop连续打印内容逐渐偏移怎么办

    Lodop打印控件中,可以使用打印机自带的纸张名称,也可以自定义纸张.(SET_PRINT_PAGESIZE语句).通常进行打印开发,为了避免浪费纸张,会用虚拟打印机效果作为依据,虚拟打印机连续打印多 ...

  8. captive portal

    刷好lineageos后默认浏览器无法上网,实际上并不是没有连上网,而是captive portal即网关设置错误,设置一下即可上网. adb shell "settings put glo ...

  9. 打包一个UWP APP

    Before packaging your app Test your app. Before you package your app for store submission, make sure ...

  10. 关于读取mapper的两种方式

    第一种: 第二种: