图论

大城市里の小女人 提交于 2020-02-21 22:53:31

图论

拓扑排序

最小生成树

最短路

#include <bits/stdc++.h>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXN = 1e5+10;
int n, m;
////加带权边

//自建结构体
struct Edge
{
  int v;
  int w;
};

Edge make_Edge(int v, int w)
{
  Edge cur;
  cur.v = v;
  cur.w = w;
  return cur;
}

vector<Edge> G[MAXN];
void addEdge(int u, int v,int w)
{
  G[u].push_back(make_Edge(v, w));
  G[v].push_back(make_Edge(u, w));
}
//pair
vector<pair<int, int>> A[MAXN];
void addedge(int u, int v, int w)
{
  A[u].push_back(make_pair(v, w));
  A[v].push_back(make_pair(u, w));
}

int main()
{

  system("pause");
  return 0;
}


/*****************************************************/
/**********************拓扑排序************************/
/*****************************************************/


/*对DAG的顶点进行排序,要求:每个顶点出现且仅出现一次
对于(u, v),若排序后u在v前,则不存在v到u的路径。
即:能够到达某个顶点(能对其产生影响)u的所有点都在u前面*/
//拓扑进不去环
//用拓扑排序找环:基环内向树,迭代的删去所有的叶子
//,剩下的就是环

queue<int> q;
vector<int> edge[MAXN];
vector<int> ans;    //ans 为拓扑排序后的输出序列
int inDeg[MAXN];    // in degree
int n, m;
void topo()
{
  for(int i=0; i < n; i++)  //n  节点的总数
  {
    if(inDeg[i] == 0) q.push(i);  //将入度为0的点入队列
  }
  while(!q.empty())
  {
    int u, v;
    u = q.front(); 
    q.pop(); // 选一个入度为0的点,出队列
    ans.push_back(u);
    for(int i=0; i < edge[u].size(); i++)
    {
      v = edge[u][i];
      inDeg[v]--;
      if(inDeg[v] == 0)   q.push(v);  
    }
  }
  //output
  if(ans.size()==n)   
  {
    for(int i=0; i<ans.size(); i++)
      printf( "%d ",ans[i] );
    printf("\n");
  }
  else printf("No Answer!\n");   //无法拓扑排序
}




/*****************************************************/
/*********************最小生成树***********************/
/*****************************************************/


/************************Prim*************************/

//每次把已访问的点的和未访问的点之间最短的边加入
//利用优先队列(堆)来存放边以获得最短的边
bool vis[MAXN];
int minc[MAXN];
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
//pair<长度, 编号>
int prim() {
    int ans = 0;
    q.push(make_pair(0, 1));
    while (!q.empty()) {
        int c = q.top().first, now = ed[q.top().second].to;
        if (!vis[now]) {
            vis[now] = true;
            ans += c;
            insert(ed[i].from, ed[i].to, ed[i].cost);
            insert(ed[i].to, ed[i].from, ed[i].cost);
            for (int i = he[now]; i; i = ne[i]) {
                Edge &e = ed[i];
                if (minc[e.to] > e.cost && !vis[e.to]) {
                    minc[e.to] = e.cost;
                    q.push(make_pair(e.cost, i));
                }
            }
        }
    }
    return ans;
}


/************************Kruskal*************************/
//按照边权进行排序,从小到大枚举每一条边,若不联通则加入最小生成
//树中。使用并查集维护连通性。
struct Edge
{
  int u;
  int v;
  int w;
};
int cmp1(Edge a, Edge b)
{
  return a.w < b.w;
}

Edge edge[MAXN];

int n, m, tot;    //tot is summary of the tree

struct myDsu      //并查集 disjoint set union 
{      
  int f[MAXN];
  void ini(int n) 
  {
    for (int i = 1; i <= n; i++) 
    {
      f[i] = i;
    }
  }
  void uni(int from, int to) {
    f[find(from)] = find(to);
  }
  int find(int x)
  {
    if(f[x] == x)
    {
      return x;
    }
    else
    {
      f[x] = find(f[x])
      return f[x];
    }
  }
}dsu;

void kruskal() {
  int k;
  dsu.ini(n);
    sort(edge, edge+m, cmp1); 
    for(int i=0; i < m; i++)
    {
        if(k == n-1) break;     //n个点需要n-1个边连接
        if(dsu.find(edge[i].u) != dsu.find(edge[i].v))
        {
            dsu.uni(edge[i].u,edge[i].v);
            tot += edge[i].w;
            k++; 
        }
    }
}

/*****************************************************/
/***********************最短路*************************/
/*****************************************************/

/***********************Folyd*************************/
const int INF = 0x3f;
int n, m;
int d[INF][INF];
void floyd()
{
  for(int k=1; k<=n; k++)
  {
    for(int i=1; i<=n; i++)
    {
      for(int j=1; i<=n; j++)
      {
        if(i != j && j != k && i != k)
        {
          d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
        }
      }
    }
  }
}

/*********************dijkstra***********************/
int d[MAXN];
bool vis[MAXN];
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq;
int dijkstra(int s, int t)
{
  memset(d, 0x3f, sizeof(d));
  d[s] = 0;
  pq.push(make_pair(0, s));
  while(!q.empty())
  {
    int now = pq.top().second;
    q.pop();
    if(!vis[now])
    {
      vis[now] = true;
      for(int i = he[now]; i; i = ne[i])
      {
        if(d[ed[i].to] > d[now] + ed[i].dist)
        {
          d[ed[i].to] = d[now] + ed[i].dist;
          pq.push(make_pair(d[ed[i].to], ed[i].to));
        }
      }
    }
  }
  return d[t] == INF ? -1 : d[t];
}


/***********************SPFA*************************/
//若某个点松弛了n次,说明有负环
//点已在队列不能入队,可以多次入队
struct Edge
{
  int from, to, dist;
};
Edge ed[MAXN];
int he[MAXN], ne[MAXN], etop = 1;
//边编号从1开始,0代表没有下一条边,对应链表的NULL
//he[i]代表点i边集中的第一条边编号,对应链表的head指针
//ne[i]代表边i的下一条边编号,对应链表中的next指针
//ed[i]代表边i的信息
const int INF = 0x3f3f3f3f;

int d[MAXN];
bool vis[MAXN];
queue<int> q;
inline int spfa(int s, int t) 
{
  q.push(s);
  vis[s] = true;
  memset(d, 0x3f, sizeof(d));
  d[s] = 0;
  while (!q.empty()) 
  {
    int now = q.front(); 
    q.pop();
    vis[now] = false;
    for (int i = he[now]; i; i = ne[i]) 
    {
      if (d[now] + ed[i].dist < d[ed[i].to]) 
      {
        d[ed[i].to] = d[now] + ed[i].dist;
        if (!vis[ed[i].to]) 
        {
          q.push(ed[i].to);
          vis[ed[i].to] = true;
        }
      }
    }
  }
  return d[t] == INF ? -1 : d[t];
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!