图论 邻接表 二分图判定 最短路问题

来源:互联网 发布:今天网络为什么不能用 编辑:程序博客网 时间:2024/06/10 22:08

一.邻接表

当边有属性或顶点有属性时

//样例一vector<int> G[MXV];//边上有属性时//struct edge{int to,cost;}//vector<edge> G[MXV];//int main(){    int V,E;    scanf("%d%d",&V,&E);    for(int i=0;i<V;++i){        int s,t;        scanf("%d%d",&s,&t);        G[s].push_back(t);//从s到t连边    }    return 0;}//样例二struct vertex{    vector<vertex*> edge;    //顶点属性};vertex G[MXV];int main(){    int V,E;    scanf("%d%d",&V,&E);    for(int i=0;i<E;++i){        int s,t;        scanf("%d %d",&s,&t);        G[s].edge.push_back(&G[t]);    }    return 0;}

二.二分图判定

vector<int> G[MXV];int V;int color[MXV];bool dfs(int v,int c){    color[v]=c;    for(int i=0;i<G[v].size();++i){        if(color[G[v][i]]==c) return false;        if(color[G[v][i]]==0&&!dfs(G[v][i],-c)) return false;    }    return true;}void Fun(){    for(int i=0;i<V;++i){        if(color[i]==0){            if(!dfs(i,1)){                puts("No");                return;            }        }    }    puts("Yes");}

三.最短路问题

3.1 Bellman-Ford算法

struct edge{int from,to,cost;};edge es[MXE];int d[MXV];int V,E:void shortest_path(int s){    for(int i=0;i<V;++i) d[i]=INF;    d[s]=0;    while(1){//最短路不会经过同一个顶点两次,最多通过|V|-1 条边,        bool update=false;        for(int i=0;i<E;++i){            edge e=es[i];            if(d[e.from]!=INF&&d[e.to]>d[e.from]+e.cost){                d[e.to]=d[e.from]+e.cost;                update=true;            }        }        if(!update) break;    }}

判断负圈

struct edge{int from,to,cost;};edge es[MXE];int d[MXV];int V,E:bool find_negative_loop(){    memset(d,0,sizeof(d));//初始化全部为0    for(int i=0;i<V;++i)        for(int j=0;j<E;++j){            edge e=es[j];            if(d[e.to]>d[e.from]+e.cost){                d[e.to]=d[e.from]+e.cost;                if(i==V-1) return true;//第V次仍然更新了,存在负圈            }        }}

3.2 dijkstra 算法

int cost[MXV][MXV];//表示e=(u,v)的权值(不存在这条边时设为INF)int d[MXV];//顶点s出发的最短距离bool used[MXV];//已经使用过的图int prev[MXV];//前趋结点int V;//顶点数void dijkstra(int s){    fill(d,d+V,INF);    fill(used,used+V,false);    fill(prev,prev+V,-1);    d[s]=0;    while(1){        int v=-1;        for(int u=0;u<V;++u){            if(!used[u]&&(v==-1||d[u]<d[v])) v=u;//从未使用过的顶点中选择一个距离最小的顶点        }        if(v==-1) break;        used[v]=true;        for(int u=0;u<V;++u){//            d[u]=min(d[u],d[v]+cost[v][u]);            if(d[u]>d[v]+cost[v][u]){                d[u]=d[v]+cost[v][u];                prev[u]=v;            }        }    }}//路径还原vector<int> get_path(int t){    vector<int> path;    for(;t!=-1;t=prev[t])        path.push_back(t);    reverse(path.begin(),path.end());    return path;}

struct edge{int to,cost;};typedef pair<int,int> P;//first是最短距离,second是顶点的编号int V;vector<edge> G[MXV];int d[MXV];void dijkstra(int s){    priority_queue<P,vector<P>,greater<P> > que;    //当所有边的权值都相同时,可以通过广搜,这时使用queue和priority_queue有同样效果    fill(d,d+V,INF);    d[s]=0;    que.push(P(0,s));    while(!que.empty()){        P p=que.top();que.pop();        int v=p.second;        if(d[v]<p.first) continue;        for(int i=0;i<G[v].size();++i){            edge e=G[v][i];            if(d[e.to]>d[v]+e.cost){                d[e.to]=d[v]+e.cost;                que.push(P(d[e.to],e.to));            }        }    }}

3.3 Floyd-Warshall 算法



void warshall_floyd(){    for(int k=0;k<V;++k)        for(int i=0;i<V;++i)            for(int j=0;j<V;++j)                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);}







原创粉丝点击