您的位置:首页 > 其它

图论模板

2014-06-05 11:48 218 查看
来自AOJ GRL Graph Algorithm切题

部分来自上交红书

转载自/article/2145909.html

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);

}

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: