图论模板

来源:互联网 发布:江苏润和软件 编辑:程序博客网 时间:2024/06/05 18:00

来自AOJ GRL Graph Algorithm切题

部分来自上交红书


转载自http://blog.csdn.net/birdstorm_s/article/details/27855101


SPFA 单源最短路

  1. int r, v, e, x, y, d;  
  2. int dist[MAXN];  
  3. bool inque[MAXN];  
  4. queue<int> que;  
  5.   
  6. vector<pair<int,int> > g[MAXN];  
  7.   
  8. void spfa()  
  9. {  
  10.     memset(dist,0x3f,sizeof dist);  
  11.     dist[r]=0;  
  12.     while(!que.empty()) que.pop();  
  13.     que.push(r);  
  14.     inque[r]=true;  
  15.     while(!que.empty()){  
  16.         int u=que.front();  
  17.         que.pop();  
  18.         int sz=g[u].size();  
  19.         For(i,0,sz){  
  20.             if(dist[u]+g[u][i].second<dist[g[u][i].first]){  
  21.                 dist[g[u][i].first]=dist[u]+g[u][i].second;  
  22.                 if(!inque[g[u][i].first]){  
  23.                     inque[g[u][i].first]=true;  
  24.                     que.push(g[u][i].first);  
  25.                 }  
  26.             }  
  27.         }  
  28.         inque[u]=false;  
  29.     }  
  30. }  
  31.   
  32. int main()  
  33. {  
  34.     scanf("%d%d%d",&v,&e,&r);  
  35.     For(i,0,e){  
  36.         scanf("%d%d%d",&x,&y,&d);  
  37.         g[x].push_back(make_pair(y,d));  
  38.     }  
  39.     spfa();  
  40.     For(i,0,v){  
  41.         if(dist[i]==0x3f3f3f3f) puts("INF");  
  42.         else printf("%d\n",dist[i]);  
  43.     }  
  44.     return 0;  
  45. }  

SPFA 单源最短路(有负边权和负圈)

  1. int v, e, x, y, d;  
  2. LL dist[MAXN][MAXN];  
  3. int cnt[MAXN];  
  4. bool inque[MAXN][MAXN];  
  5. queue<int> que;  
  6.   
  7. vector<pair<int,int> > g[MAXN];  
  8.   
  9. bool spfa()  
  10. {  
  11.     For(i,0,v) For(j,0,v) dist[i][j]=LONG_LONG_MAX;  
  12.     For(r,0,v){  
  13.         dist[r][r]=0;  
  14.         memset(cnt,0,sizeof cnt);  
  15.         while(!que.empty()) que.pop();  
  16.         que.push(r);  
  17.         inque[r][r]=true;  
  18.         while(!que.empty()){  
  19.             int u=que.front();  
  20.             que.pop();  
  21.             int sz=g[u].size();  
  22.             For(i,0,sz){  
  23.                 int id=g[u][i].first;  
  24.                 if(dist[r][u]+g[u][i].second<dist[r][id]){  
  25.                     dist[r][id]=dist[r][u]+g[u][i].second;  
  26.                     if(!inque[r][id]){  
  27.                         cnt[id]++;  
  28.                         if(cnt[id]>e) return false;  
  29.                         inque[r][id]=true;  
  30.                         que.push(id);  
  31.                     }  
  32.                 }  
  33.             }  
  34.             inque[r][u]=false;  
  35.         }  
  36.     }  
  37.     return true;  
  38. }  
  39.   
  40. int main()  
  41. {  
  42.     scanf("%d%d",&v,&e);  
  43.     For(i,0,e){  
  44.         scanf("%d%d%d",&x,&y,&d);  
  45.         g[x].push_back(make_pair(y,d));  
  46.     }  
  47.     if(spfa()){  
  48.         For(i,0,v) For(j,0,v){  
  49.             if(dist[i][j]==LONG_LONG_MAX) printf("INF%c",j==v-1?'\n':' ');  
  50.             else printf("%lld%c",dist[i][j],j==v-1?'\n':' ');  
  51.         }  
  52.     }  
  53.     else puts("NEGATIVE CYCLE");  
  54.     return 0;  
  55. }  



dfs 判环(1有环2无环)

dfs中第二个判断末尾若将r节点加入L队列即为topo排序

  1. int v, e, x, y;  
  2. int inque[MAXN];  
  3. bool flag=false;  
  4.    
  5. vector<int> g[MAXN];  
  6.    
  7. void dfs(int r)  
  8. {  
  9.     if(inque[r]==1){  
  10.         flag=true;  
  11.     }  
  12.     if(!inque[r]){  
  13.         inque[r]=1;  
  14.         int sz=g[r].size();  
  15.         For(i,0,sz) dfs(g[r][i]);  
  16.         inque[r]=-1;  
  17.     }  
  18. }  
  19.    
  20. int main()  
  21. {  
  22.     scanf("%d%d",&v,&e);  
  23.     For(i,0,e){  
  24.         scanf("%d%d",&x,&y);  
  25.         g[x].push_back(y);  
  26.     }  
  27.     For(i,0,v){  
  28.         if(!inque[i]) dfs(i);  
  29.         if(flag) break;  
  30.     }  
  31.     printf("%d\n",flag);  
  32.     return 0;  
  33. }  


prim

  1. int x, y, v, e;  
  2. LL d, ans;  
  3. LL dist[MAXN];  
  4. bool vis[MAXN];  
  5.   
  6. vector<pair<int,LL> > g[MAXN];  
  7.   
  8. LL prim()  
  9. {  
  10.     memset(vis,0,sizeof vis);  
  11.     ans=0;  
  12.     For(i,0,v) dist[i]=LONG_LONG_MAX;  
  13.     dist[0]=0;  
  14.     For(i,0,v){  
  15.         int mark=-1;  
  16.         For(j,0,v){  
  17.             if(!vis[j]){  
  18.                 if(mark==-1) mark=j;  
  19.                 else if(dist[j]<dist[mark]) mark=j;  
  20.             }  
  21.         }  
  22.         if(mark==-1) break;  
  23.         vis[mark]=true;  
  24.         ans+=dist[mark];  
  25.         int sz=g[mark].size();  
  26.         For(j,0,sz){  
  27.             int u=g[mark][j].first;  
  28.             if(!vis[u]){  
  29.                 dist[u]=min(dist[u],g[mark][j].second);  
  30.             }  
  31.         }  
  32.     }  
  33.     return ans;  
  34. }  
  35.   
  36. int main()  
  37. {  
  38.     scanf("%d%d",&v,&e);  
  39.     For(i,0,e){  
  40.         scanf("%d%d%lld",&x,&y,&d);  
  41.         g[x].push_back(make_pair(y,d));  
  42.         g[y].push_back(make_pair(x,d));  
  43.     }  
  44.     printf("%lld\n",prim());  
  45.     return 0;  
  46. }  



kruscal

  1. int x, y, v, e, tot;  
  2. LL d, ans;  
  3. int father[MAXN];  
  4.   
  5. struct edge{  
  6.     int from, to, w;  
  7.     edge(int from=0, int to=0, int w=0): from(from),to(to),w(w) {}  
  8. }g[MAXN];  
  9.   
  10. int cmp(edge a, edge b)  
  11. {  
  12.     return a.w<b.w;  
  13. }  
  14.   
  15. void addedge(int x, int y, int w)  
  16. {  
  17.     g[tot].from=x, g[tot].to=y, g[tot].w=w; tot++;  
  18.     g[tot].from=x, g[tot].to=y, g[tot].w=w; tot++;  
  19. }  
  20.   
  21. int getfather(int x)  
  22. {  
  23.     if(father[x]==x) return x;  
  24.     else return father[x]=getfather(father[x]);  
  25. }  
  26.   
  27. LL kruscal()  
  28. {  
  29.     sort(g,g+tot,cmp);  
  30.     int cnt=v;  
  31.     ans=0;  
  32.     For(i,0,v) father[i]=i;  
  33.     For(i,0,tot){  
  34.         int t1=getfather(g[i].from);  
  35.         int t2=getfather(g[i].to);  
  36.         if(t1!=t2){  
  37.             father[t1]=father[t2];  
  38.             ans+=g[i].w;  
  39.             if(cnt==1) break;  
  40.         }  
  41.     }  
  42.     return ans;  
  43. }  
  44.   
  45. int main()  
  46. {  
  47.     scanf("%d%d",&v,&e);  
  48.     tot=0;  
  49.     For(i,0,e){  
  50.         scanf("%d%d%lld",&x,&y,&d);  
  51.         addedge(x,y,d);  
  52.     }  
  53.     printf("%lld\n",kruscal());  
  54.     return 0;  
  55. }  


最小树形图

  1. int x, y, v, e, tot, r;  
  2. double d, sum;  
  3. double g[MAXN][MAXN];  
  4. int more, que[MAXN], eg[MAXN];  
  5. bool pass[MAXN], used[MAXN];  
  6.   
  7.   
  8. inline void combine(int id, double &sum)  
  9. {  
  10.     int tot=0, from;  
  11.     for(;id!=0&&!pass[id];id=eg[id]){  
  12.         que[tot++]=id;  
  13.         pass[id]=true;  
  14.     }  
  15.     for(from=0;from<tot&&que[from]!=id;++from);  
  16.     if(from==tot) return;  
  17.     more=1;  
  18.     For(i,from,tot){  
  19.         sum+=g[eg[que[i]]][que[i]];  
  20.         if(i!=from){  
  21.             used[que[i]]=true;  
  22.             For(j,1,v+1) if(!used[j]){  
  23.                 g[id][j]=min(g[id][j],g[que[i]][j]);  
  24.             }  
  25.         }  
  26.     }  
  27.     For(i,1,v+1) if(!used[i]&&i!=id){  
  28.         For(j,from,tot){  
  29.             int k=que[j];  
  30.             g[i][id]=min(g[i][id],g[i][k]-g[eg[k]][k]);  
  31.         }  
  32.     }  
  33. }  
  34.   
  35.   
  36. double mdst(int root)  
  37. {  
  38.     sum=0;  
  39.     memset(used,0,sizeof used);  
  40.     for(more=1;more;){  
  41.         more=0;  
  42.         memset(eg,0,sizeof eg);  
  43.         For(i,1,v+1){  
  44.             if(!used[i]&&i!=root){  
  45.                 int k=0;  
  46.                 For(j,1,v+1){  
  47.                     if(!used[j]&&j!=i){  
  48.                         if(k==0||g[j][i]<g[k][i])  
  49.                             k=j;  
  50.                     }  
  51.                 }  
  52.                 eg[i]=k;  
  53.             }  
  54.         }  
  55.         memset(pass,0,sizeof pass);  
  56.         For(i,1,v+1){  
  57.             if(!used[i]&&!pass[i]&&i!=root)  
  58.                 combine(i,sum);  
  59.         }  
  60.     }  
  61.     For(i,1,v+1) if(!used[i]&&i!=root) sum+=g[eg[i]][i];  
  62.     return sum;  
  63. }  
  64.   
  65.   
  66. int main()  
  67. {  
  68.     scanf("%d%d%d",&v,&e,&r);  
  69.     For(i,0,e){  
  70.         scanf("%d%d%lf",&x,&y,&d);  
  71.         g[x+1][y+1]=d;  
  72.     }  
  73.     printf("%.0lf\n",mdst(r+1));  
  74.     return 0;  
  75. }  


查找桥和关节点(割点)

  1. int v, e, x, y;  
  2. int vis[MAXN], low[MAXN], dfn[MAXN];  
  3. bool cut[MAXN], bridge[MAXN][MAXN];  
  4.   
  5. vector<int> g[MAXN];  
  6.   
  7. void cut_bridge(int cur, int father, int dep, int n)  
  8. {  
  9.     vis[cur]=1; dfn[cur]=low[cur]=dep;  
  10.     int children=0;  
  11.     int sz=g[cur].size();  
  12.     For(i,0,sz){  
  13.         int u=g[cur][i];  
  14.         if(u!=father&&vis[u]==1){  
  15.             if(dfn[u]<low[cur])  
  16.                 low[cur]=dfn[u];  
  17.         }  
  18.         if(!vis[u]){  
  19.             cut_bridge(u,cur,dep+1,n);  
  20.             children++;  
  21.             if(low[u]<low[cur]) low[cur]=low[u];  
  22.             if(father==-1&&children>1||father!=-1&&low[u]>=dfn[cur]) cut[cur]=true;  
  23.             if(low[u]>dfn[cur]) bridge[cur][u]=bridge[u][cur]=true;  
  24.         }  
  25.     }  
  26.     vis[cur]=2;  
  27. }  
  28.   
  29. int main()  
  30. {  
  31.     scanf("%d%d",&v,&e);  
  32.     For(i,0,e){  
  33.         scanf("%d%d",&x,&y);  
  34.         g[x].push_back(y);  
  35.         g[y].push_back(x);  
  36.     }  
  37.     cut_bridge(0,-1,0,v);  
  38.     For(i,0,v) if(cut[i]) printf("%d\n",i);  
  39.     return 0;  
  40. }  




前向星建图

  1. struct graph{  
  2.     typedef vector<int> vi;  
  3.     vi info, next, to;  
  4.     graph(int n=0, int m=0): to(0), next(0) {  
  5.         info.resize(n);  
  6.         next.reserve(m);  
  7.         to.reserve(m);  
  8.     }  
  9.   
  10.     int edge_size(){        //返回边的数量  
  11.         return to.size();  
  12.     }  
  13.     int vertex_size(){      //返回值为最大点的编号-1  
  14.         return info.size();  
  15.     }  
  16.     void expand(int i){  
  17.         if(info.size()<i+1)  
  18.             info.resize(i+1);  
  19.     }  
  20.     void add(int i, int j){  //添加一条i到j的边  
  21.         expand(i), expand(j);  
  22.         to.push_back(j);  
  23.         next.push_back(info[i]);  
  24.         info[i]=to.size()-1;  
  25.     }  
  26.     void del_back(){         //删除最后一次添加的边  
  27.         int i;  
  28.         for(int i=0; i<info.size(); i++){  
  29.             if(info[i]==to.size()-1){  
  30.                 info[i]=next.back();  
  31.                 break;  
  32.             }  
  33.         }  
  34.         to.pop_back();  
  35.         next.pop_back();  
  36.     }  
  37.     void clear(){            //清空  
  38.         info.clear();  
  39.         next.resize(0);  
  40.         to.resize(0);  
  41.     }  
  42. };  
0 0
原创粉丝点击