来自AOJ GRL Graph Algorithm切题
部分来自上交红书
SPFA 单源最短路
int r, v, e, x, y, d;
int dist[MAXN];
bool inque[MAXN];
queue<int> que;
vector<pair<int,int> > g[MAXN];
void spfa()
{
memset(dist,0x3f,sizeof dist);
dist[r]=0;
while(!que.empty()) que.pop();
que.push(r);
inque[r]=true;
while(!que.empty()){
int u=que.front();
que.pop();
int sz=g[u].size();
For(i,0,sz){
if(dist[u]+g[u][i].second<dist[g[u][i].first]){
dist[g[u][i].first]=dist[u]+g[u][i].second;
if(!inque[g[u][i].first]){
inque[g[u][i].first]=true;
que.push(g[u][i].first);
}
}
}
inque[u]=false;
}
}
int main()
{
scanf("%d%d%d",&v,&e,&r);
For(i,0,e){
scanf("%d%d%d",&x,&y,&d);
g[x].push_back(make_pair(y,d));
}
spfa();
For(i,0,v){
if(dist[i]==0x3f3f3f3f) puts("INF");
else printf("%d\n",dist[i]);
}
return 0;
}
SPFA 单源最短路(有负边权和负圈)
int v, e, x, y, d;
LL dist[MAXN][MAXN];
int cnt[MAXN];
bool inque[MAXN][MAXN];
queue<int> que;
vector<pair<int,int> > g[MAXN];
bool spfa()
{
For(i,0,v) For(j,0,v) dist[i][j]=LONG_LONG_MAX;
For(r,0,v){
dist[r][r]=0;
memset(cnt,0,sizeof cnt);
while(!que.empty()) que.pop();
que.push(r);
inque[r][r]=true;
while(!que.empty()){
int u=que.front();
que.pop();
int sz=g[u].size();
For(i,0,sz){
int id=g[u][i].first;
if(dist[r][u]+g[u][i].second<dist[r][id]){
dist[r][id]=dist[r][u]+g[u][i].second;
if(!inque[r][id]){
cnt[id]++;
if(cnt[id]>e) return false;
inque[r][id]=true;
que.push(id);
}
}
}
inque[r][u]=false;
}
}
return true;
}
int main()
{
scanf("%d%d",&v,&e);
For(i,0,e){
scanf("%d%d%d",&x,&y,&d);
g[x].push_back(make_pair(y,d));
}
if(spfa()){
For(i,0,v) For(j,0,v){
if(dist[i][j]==LONG_LONG_MAX) printf("INF%c",j==v-1?'\n':' ');
else printf("%lld%c",dist[i][j],j==v-1?'\n':' ');
}
}
else puts("NEGATIVE CYCLE");
return 0;
}
dfs 判环(1有环2无环)
dfs中第二个判断末尾若将r节点加入L队列即为topo排序
int v, e, x, y;
int inque[MAXN];
bool flag=false;
vector<int> g[MAXN];
void dfs(int r)
{
if(inque[r]==1){
flag=true;
}
if(!inque[r]){
inque[r]=1;
int sz=g[r].size();
For(i,0,sz) dfs(g[r][i]);
inque[r]=-1;
}
}
int main()
{
scanf("%d%d",&v,&e);
For(i,0,e){
scanf("%d%d",&x,&y);
g[x].push_back(y);
}
For(i,0,v){
if(!inque[i]) dfs(i);
if(flag) break;
}
printf("%d\n",flag);
return 0;
}
prim
int x, y, v, e;
LL d, ans;
LL dist[MAXN];
bool vis[MAXN];
vector<pair<int,LL> > g[MAXN];
LL prim()
{
memset(vis,0,sizeof vis);
ans=0;
For(i,0,v) dist[i]=LONG_LONG_MAX;
dist[0]=0;
For(i,0,v){
int mark=-1;
For(j,0,v){
if(!vis[j]){
if(mark==-1) mark=j;
else if(dist[j]<dist[mark]) mark=j;
}
}
if(mark==-1) break;
vis[mark]=true;
ans+=dist[mark];
int sz=g[mark].size();
For(j,0,sz){
int u=g[mark][j].first;
if(!vis[u]){
dist[u]=min(dist[u],g[mark][j].second);
}
}
}
return ans;
}
int main()
{
scanf("%d%d",&v,&e);
For(i,0,e){
scanf("%d%d%lld",&x,&y,&d);
g[x].push_back(make_pair(y,d));
g[y].push_back(make_pair(x,d));
}
printf("%lld\n",prim());
return 0;
}
kruscal
int x, y, v, e, tot;
LL d, ans;
int father[MAXN];
struct edge{
int from, to, w;
edge(int from=0, int to=0, int w=0): from(from),to(to),w(w) {}
}g[MAXN];
int cmp(edge a, edge b)
{
return a.w<b.w;
}
void addedge(int x, int y, int w)
{
g[tot].from=x, g[tot].to=y, g[tot].w=w; tot++;
g[tot].from=x, g[tot].to=y, g[tot].w=w; tot++;
}
int getfather(int x)
{
if(father[x]==x) return x;
else return father[x]=getfather(father[x]);
}
LL kruscal()
{
sort(g,g+tot,cmp);
int cnt=v;
ans=0;
For(i,0,v) father[i]=i;
For(i,0,tot){
int t1=getfather(g[i].from);
int t2=getfather(g[i].to);
if(t1!=t2){
father[t1]=father[t2];
ans+=g[i].w;
if(cnt==1) break;
}
}
return ans;
}
int main()
{
scanf("%d%d",&v,&e);
tot=0;
For(i,0,e){
scanf("%d%d%lld",&x,&y,&d);
addedge(x,y,d);
}
printf("%lld\n",kruscal());
return 0;
}
最小树形图
int x, y, v, e, tot, r;
double d, sum;
double g[MAXN][MAXN];
int more, que[MAXN], eg[MAXN];
bool pass[MAXN], used[MAXN];
inline void combine(int id, double &sum)
{
int tot=0, from;
for(;id!=0&&!pass[id];id=eg[id]){
que[tot++]=id;
pass[id]=true;
}
for(from=0;from<tot&&que[from]!=id;++from);
if(from==tot) return;
more=1;
For(i,from,tot){
sum+=g[eg[que[i]]][que[i]];
if(i!=from){
used[que[i]]=true;
For(j,1,v+1) if(!used[j]){
g[id][j]=min(g[id][j],g[que[i]][j]);
}
}
}
For(i,1,v+1) if(!used[i]&&i!=id){
For(j,from,tot){
int k=que[j];
g[i][id]=min(g[i][id],g[i][k]-g[eg[k]][k]);
}
}
}
double mdst(int root)
{
sum=0;
memset(used,0,sizeof used);
for(more=1;more;){
more=0;
memset(eg,0,sizeof eg);
For(i,1,v+1){
if(!used[i]&&i!=root){
int k=0;
For(j,1,v+1){
if(!used[j]&&j!=i){
if(k==0||g[j][i]<g[k][i])
k=j;
}
}
eg[i]=k;
}
}
memset(pass,0,sizeof pass);
For(i,1,v+1){
if(!used[i]&&!pass[i]&&i!=root)
combine(i,sum);
}
}
For(i,1,v+1) if(!used[i]&&i!=root) sum+=g[eg[i]][i];
return sum;
}
int main()
{
scanf("%d%d%d",&v,&e,&r);
For(i,0,e){
scanf("%d%d%lf",&x,&y,&d);
g[x+1][y+1]=d;
}
printf("%.0lf\n",mdst(r+1));
return 0;
}
查找桥和关节点(割点)
int v, e, x, y;
int vis[MAXN], low[MAXN], dfn[MAXN];
bool cut[MAXN], bridge[MAXN][MAXN];
vector<int> g[MAXN];
void cut_bridge(int cur, int father, int dep, int n)
{
vis[cur]=1; dfn[cur]=low[cur]=dep;
int children=0;
int sz=g[cur].size();
For(i,0,sz){
int u=g[cur][i];
if(u!=father&&vis[u]==1){
if(dfn[u]<low[cur])
low[cur]=dfn[u];
}
if(!vis[u]){
cut_bridge(u,cur,dep+1,n);
children++;
if(low[u]<low[cur]) low[cur]=low[u];
if(father==-1&&children>1||father!=-1&&low[u]>=dfn[cur]) cut[cur]=true;
if(low[u]>dfn[cur]) bridge[cur][u]=bridge[u][cur]=true;
}
}
vis[cur]=2;
}
int main()
{
scanf("%d%d",&v,&e);
For(i,0,e){
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
cut_bridge(0,-1,0,v);
For(i,0,v) if(cut[i]) printf("%d\n",i);
return 0;
}
前向星建图
struct graph{
typedef vector<int> vi;
vi info, next, to;
graph(int n=0, int m=0): to(0), next(0) {
info.resize(n);
next.reserve(m);
to.reserve(m);
}
int edge_size(){ //返回边的数量
return to.size();
}
int vertex_size(){ //返回值为最大点的编号-1
return info.size();
}
void expand(int i){
if(info.size()<i+1)
info.resize(i+1);
}
void add(int i, int j){ //添加一条i到j的边
expand(i), expand(j);
to.push_back(j);
next.push_back(info[i]);
info[i]=to.size()-1;
}
void del_back(){ //删除最后一次添加的边
int i;
for(int i=0; i<info.size(); i++){
if(info[i]==to.size()-1){
info[i]=next.back();
break;
}
}
to.pop_back();
next.pop_back();
}
void clear(){ //清空
info.clear();
next.resize(0);
to.resize(0);
}
};