图论的一些算法(c++)

  1. ```
  2. #include<bits/stdc++.h>//请使用支持c++11的环境 
  3. #pragma GCC optimize(2)
  4. using namespace std;
  5. typedef pair<int,int>PII;
  6. #define endl "\n"
  7. typedef unsigned long long ull;
  8. typedef long long ll;
  9. const int M=1010;
  10. const int INF=0x3f3f3f3f;
  11. const int mod=1e9+7;
  12. const int N=2e5+10;
  13. int dx[4]={0,1,0,-1};
  14. int dy[4]={-1,0,1,0};
  15. int w[M][M],s[M][M],dist[M],back[M],p[M],cnt[M];
  16. int n;//点数 
  17. int len;//边数
  18. struct P{
  19.     int ne,w;
  20. };
  21. struct Q{
  22.     int a,b,w;
  23. }b[M*M];
  24. bool cmp(Q q,Q w){
  25.     return q.w<w.w;
  26. }
  27. vector<P> a[M];
  28. bool st[M];
  29. int find(int x){//并查集 
  30.     if(p[x]==x) return x;
  31.     return p[x]=find(p[x]);
  32. }
  33. void merge(int q,int w){//并查集合并优化 
  34.     q=find(q);w=find(w);
  35.     if(cnt[q]==cnt[w]){
  36.         p[w]=q;
  37.         cnt[q]++;
  38.     }
  39.     else if(cnt[q]<cnt[w]){
  40.         p[q]=w;
  41.     }
  42.     else{
  43.         p[w]=q;
  44.     }
  45. }
  46. void dfs_1(int x){//用邻接表 
  47.     st[x]=1;
  48.     cout<<x<<" ";
  49.     for(int i=0;i<a[x].size();i++){
  50.         if(!st[a[x][i].ne])
  51.         dfs_1(a[x][i].ne);
  52.     }
  53. }
  54. void dfs_2(int x){
  55.     st[x]=1;
  56.     cout<<x<<" ";
  57.     for(int i=1;i<=n;i++){
  58.         if(!st[i]&&w[x][i]!=0x3f3f3f3f){
  59.             dfs_2(i);
  60.         }
  61.     }
  62. }
  63. void bfs_1(){
  64.     memset(st,0,sizeof st);
  65.     queue<int> q;
  66.     q.push(1);//默认从1开始
  67.     st[1]=1;
  68.     while(q.size()){
  69.         int e=q.front();q.pop();
  70.         cout<<e<<" ";
  71.         for(int i=0;i<a[e].size();i++){
  72.             if(!st[a[e][i].ne]){
  73.                 st[a[e][i].ne]=1;
  74.                 q.push(a[e][i].ne);
  75.             }
  76.         }
  77.     } 
  78.     
  79. }
  80. void bfs_2(){
  81.     memset(st,0,sizeof st);
  82.     queue<int> q;
  83.     q.push(1);//默认从1开始
  84.     st[1]=1;
  85.     while(q.size()){
  86.         int e=q.front();q.pop();
  87.         cout<<e<<" ";
  88.         for(int i=1;i<=n;i++){
  89.             if(!st[i]&&w[e][i]!=0x3f3f3f3f){
  90.                 st[i]=1;
  91.                 q.push(i);
  92.             }
  93.         }
  94.     } 
  95. }
  96. void dijkstra(int start,int end){//复杂度O(n*n+m) 
  97.     memset(dist,0x3f,sizeof dist);
  98.     memset(st,0,sizeof st);
  99.     dist[start]=0;
  100.     int z=start;
  101.     while(!st[end]&&z!=-1){
  102.         st[z]=1;
  103.         for(int i=0;i<a[z].size();i++){
  104.             dist[a[z][i].ne]=min(dist[a[z][i].ne],dist[z]+a[z][i].w);
  105.         }
  106.         z=-1;
  107.         for(int i=1;i<=n;i++){
  108.             if(!st[i]&&dist[i]!=0x3f3f3f3f){
  109.                 if(z==-1||dist[z]>dist[i]) z=i;
  110.             } 
  111.         }
  112.     }
  113.     if(!st[end]) cout<<"不可达"<<endl;
  114.     else cout<<dist[end]<<endl;
  115. }
  116. void dijkstra_heap(int start,int end){//复杂度O(nlog n+m) 
  117.     memset(dist,0x3f,sizeof dist);
  118.     memset(st,0,sizeof st);
  119.     priority_queue<PII,vector<PII>,greater<PII>> heap;
  120.     heap.push({0,start});
  121.     dist[start]=0;
  122.     while(!st[end]&&heap.size()){
  123.         int p=heap.top().second;heap.pop();
  124.         if(st[p]) continue;
  125.         st[p]=1;
  126.         cout<<p<<" ";
  127.         for(int i=0;i<a[p].size();i++){
  128.             if(st[a[p][i].ne]) continue;
  129.             if(dist[a[p][i].ne]>dist[p]+a[p][i].w){
  130.                 dist[a[p][i].ne]=dist[p]+a[p][i].w;
  131.                 heap.push({dist[a[p][i].ne],a[p][i].ne});
  132.             }
  133.         }
  134.     }
  135.     if(dist[end]==0x3f3f3f3f) cout<<"不可达"<<endl;
  136.     else cout<<dist[end]<<endl;
  137. }
  138. void floyd(){
  139.     for(int i=1;i<=n;i++){
  140.         for(int j=1;j<=n;j++){
  141.             for(int k=1;k<=n;k++) w[j][k]=min(w[j][k],w[j][i]+w[i][k]);
  142.         }
  143.     }
  144.     int q;
  145.     cin>>q;//询问次数
  146.     while(q--){
  147.         int r,e;
  148.         cin>>r>>e;
  149.         cout<<w[r][e]<<endl;//输出r到e的最短路 
  150.     } 
  151. }
  152. void bellman_ford(int start,int end){
  153.     int k=n;
  154.     memset(dist,0x3f,sizeof dist);
  155.     dist[start]=0;
  156.     while(k--){
  157.         memcpy(back,dist,sizeof back);
  158.         for(int i=2;i<=(len<<1|1);i++){
  159.             dist[b[i].b]=min(back[b[i].a]+b[i].w,dist[b[i].b]);
  160.         }
  161.     }
  162.     if(dist[end]>=0x3f3f3f3f/2) cout<<"不可达"<<endl;
  163.     else cout<<dist[end]<<endl;
  164. }
  165. void spfa(int start,int end){//O(n*m) 
  166.     memset(dist,0x3f,sizeof dist);
  167.     memset(st,0,sizeof st);
  168.     queue<int> q;
  169.     q.push(start);
  170.     dist[start]=0;
  171.     while(q.size()){
  172.         int p=q.front();q.pop();
  173.         st[p]=0;
  174.         for(int i=0;i<a[p].size();i++){
  175.             if(dist[a[p][i].ne]>dist[p]+a[p][i].w){
  176.                 dist[a[p][i].ne]=dist[p]+a[p][i].w;
  177.                 if(!st[a[p][i].ne]) q.push(a[p][i].ne);
  178.                 st[a[p][i].ne]=1;
  179.             }
  180.         }
  181.     }
  182.     if(dist[end]>=0x3f3f3f3f/2) cout<<"不可达"<<endl;
  183.     else cout<<dist[end]<<endl;
  184. }
  185. void prim(){
  186.     ll ans=0;
  187.     memset(dist, 0x3f, sizeof dist);
  188.     memset(st,0,sizeof st);
  189.     for(int i=0;i<n;i++)
  190.     {
  191.         int t=-1;
  192.         for(int j=1;j<=n;j++)
  193.         {
  194.             if(!st[j]&&(t==-1||dist[t]>dist[j])) t=j;
  195.         }
  196.         if (i&&dist[t]==0x3f3f3f3f){
  197.             cout<<"不是连通图"<<endl;
  198.             return;
  199.         }
  200.         if(i) ans+=dist[t];
  201.         for(int j=2;j<=(len<<1|1);j++)
  202.         {
  203.             if(dist[j]>w[t][j]&&!st[j])
  204.             dist[j]=min(dist[j],s[t][j]);
  205.         }
  206.         st[t]=1;
  207.     }
  208.     cout<<ans<<endl;
  209. }
  210. void kruskal(){//复杂度O(mlog m) 
  211.     for(int i=1;i<=n;i++) p[i]=i;
  212.     sort(b+1,b+len+1,cmp);
  213.     int cnt=0;ll ans=0;
  214.     for(int i=2;i<=(len<<1|1);i++){
  215.         int q=find(b[i].a),w=find(b[i].b);
  216.         if(q!=w){
  217.             cnt++;
  218.             ans+=b[i].w;
  219.             merge(q,w);
  220.         }
  221.     }
  222.     if(cnt==n-1) cout<<ans<<endl;
  223.     else cout<<"不可达"<<endl; 
  224. }
  225. void solve()
  226. {
  227.     
  228.     cin>>n>>len;//点数上限为1009,边数上限为1010*1010-2
  229.     memset(w,0x3f,sizeof w);//认为距离上限不超过 0x3f3f3f3f
  230.     memset(s,0x3f,sizeof s);
  231.     for(int i=1;i<=len;i++){//读入无向边 base_1
  232.         int q,r,e;//e为边的长度
  233.         cin>>q>>r>>e;
  234.         if(q==r) continue;
  235.         s[q][r]=w[q][r]=min(w[q][r],e);a[q].push_back({r,e});b[i<<1]={q,r,e}; 
  236.         s[r][q]=w[r][q]=min(w[r][q],q);a[r].push_back({q,e});b[i<<1|1]={r,q,e};//若想为有向边,请给这一行前面加// 
  237.     }
  238.     //默认从1开始
  239.     dfs_1(1);
  240.     cout<<endl;
  241.     memset(st,0,sizeof st);
  242.     dfs_2(1);
  243.     cout<<endl;
  244.     bfs_1();
  245.     cout<<endl;
  246.     bfs_2();
  247.     cout<<endl;
  248.     int start,end;
  249.     cin>>start>>end;
  250.     dijkstra(start,end);
  251.     cin>>start>>end;
  252.     dijkstra_heap(start,end);
  253.        floyd();//请输入询问次数 再输入起始位置和终止位置
  254.     cin>>start>>end; 
  255.     bellman_ford(start,end);
  256.     cin>>start>>end; 
  257.     spfa(start,end); 
  258.     prim();
  259.     kruskal();
  260. }
  261. int main()
  262. {
  263.     //下列三行是开启同步,加快输入输出的,输出将会在所有输入完成后,若想按程序运行顺序输出请删除下列三行 
  264.         ios_base::sync_with_stdio(0);
  265.         cin.tie(0);
  266.         cout.tie(0);
  267.         solve();
  268.         return 0;
  269. ```
  270.  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值