图论(并查集 最小生成树 最短路径 关键路径)

并查集

/*
* 并查集的应用
*
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
#define MAXN 1000
int matrix[MAXN][MAXN]; // 定义距离
int parent[MAXN];      // 其父亲节点
using namespace std;
void _init()
{
    for( int  i=0; i<=999; i++)
    {
        parent[i]=i;
    }
}
int FindParent( int i ) // 找父节点
{
    int pos=i;
    if(parent[pos]!=pos)
    {
        parent[pos]=FindParent(parent[pos]); //不要写成死循环
    }
    return parent[pos];
}

void  _union( int x, int y )
{
    //
    int x1=FindParent(x);
    int y1=FindParent(y);
    if(x1<y1){
        parent[y1]=x1;
    }
    else
        parent[x1]=y1;
}
// 就在做集合的合并时候出现的问题 如果是 parent[pos]=-1 以及parent[pos]=-2;
//没有使用parent[pos]=pos方便
int main()
{
  int  answer=-1;
    int nodeNum;
    int edgeNum;
    cin>>nodeNum>>edgeNum;
    _init();
    for( int i=0; i<edgeNum;i++)
    {
        int pos1,pos2;
        cin>>pos1>>pos2;
      _union(pos1,pos2);
    }
    for( int i=0; i<nodeNum;i++)
    {
  if(parent[i]==i){
    answer++;
    }
    }
 cout<<answer;
    return 0;
}

那么这段关于并查集的代码, 自己开始parent[]初始化-2 , 判断是否终止使用-2这种方式并不方便, 不如使用parent[ i]=i

最小生成树代码 :

/*
* 最小生成树
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
#include<algorithm>
#define MAXN 1000
int parent[MAXN]; //父辈
using namespace std;
struct Edge
{
    int from ;
    int to;
    int weight;
    bool operator< ( Edge b)
    {
        return  weight<b.weight;
    }
};

struct Edge node[MAXN];


void _init( int  n )
{
    for( int  i =0; i<n; i++)
    {
        parent[i]=i;
    }

}

int Find( int x)
{
    if(parent[x]!=x)
    {
        parent[x]=Find(parent[x]);
    }
    return parent[x];
}
void  _union( int x,  int  y)
{

    int a=Find(x);
    int b=Find(y);
    if(a<b)
    {
        parent[a]=b;
    }
    else
    {
        parent[b]=a;
    }
}
//克鲁斯卡尔算法
int Kruskar(  int num)
{
    int sum=0;
    for( int i =0; i<num; i++) // 边数
    {
        Edge current= node[i];
        if(Find(current.to)!=Find(current.from)) // 并不用使用visit了
        {
            _union(current.to,current.from);
             sum+=current.weight;
        }
    }
  return sum;
}
int main()
{
    int n; int num;
    cin>>n>>num;
    _init(n);
    for( int i =0;i<n;i++){
        cin>>node[i].to>>node[i].from>>node[i].weight;
    }
    sort(node,node+n);
    cout<<Kruskar(n);
}

最短路径

/*
* 最短路径
看来还是应该考虑一下非连通图的情况 
下面的并没有考虑
以下的代码使用vector 存储邻接表来表示图
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
#include<vector>
#include<algorithm>
#define MAXN 1000 
using namespace std;
int  dis[MAXN]; 
struct Edge
{
    int to;
    int weight;
  Edge(int a, int t):to(a),weight(t);
    bool operator< ( Edge b)
    {
        return  weight<b.weight;
    }
};
vector<Edge>graph[MAXN];
//存储邻接表



struct Node {
  int node_num;//节点编号
  int distance ;//定义距离
  Node( int n ,int d):node_num(n),distance(d);
  bool operator <(Node b){
  return distance>b.distance;
  }
};
struct Edge node[MAXN];

void  update( int updateNodeNum){

for( int  i =0;i<99;i++){
    if(dis[updateNodeNum][i]!=0){
        if(dis[0][i]>dis[0][updateNodeNum]+dis[updateNodeNum][i]){
           dis[0][i]=dis[0][updateNodeNum]+dis[updateNodeNum][i]; 
        }
    }
}

} //随随着节点的加入所有与它相连的都更新

void Dijkstra( int s){
priority_queue<Node>myQueue; //优先队列
dis[s]=0;
myQueue.push(Node(s,dis[s]));
while(!myQueue.empty()){
int  u=myQueue.top().node_num;
    for( int  i =0;i<graph[u].size();i++){
        int  v=graph[u][i].to;
        int d=graph[u][i].length;
        if(dis[v]>dis[u]+d){
            dis[v]=dis[u]+d;
            myQueue.push(Node(v,dis[v]));
            //这种写法之后不能用 distance 也可以在做一个 bool visit[]
        }
    }
}


} // 最短路径算法 
int main(){

int  n, int  m;
while( scanf("%d%d",&n,&m)!=EOF){
    memset(graph,0,sizeof(graph));
    fill(dis,dis+n,10000);
}


while(m--){
    int from ;
    int to;
    int length;
    cin>>from>>to>>length;
    graph[from].push_back(Edge(to,length));
    graph[to].push_back(Edge(from,length));
    
    int s,t;
    cin>>s>>t;
    Dijkstra(s)
    if(dis[t]==100000){
        cout<<"不可达"<<endl;
    }
}
return 0;
}

拓扑排序

/*
*   DAG :拓扑排序
*   拓扑排序是 利用队列 根据入度以及出度
*
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
#include<vector>
#include<algorithm>
#define MAXN 1000
using namespace std;
int  inDegree[MAXN]; // 定义入度

vector<int> graph[MAXN];
vector<int > TopSort( int n ){ //topSort  

vector<int> myQueue; //存放结果
priority_queue<int , vector<int>,greater<int>>node;

for( int i=0;i<=n;i++){
    if(inDegree[i]==0){
        node.push(i);
        //将节点近队列
    }
}
while(!node.empty()){ //节点不为空时候
    int  u=node.top();
    node.pop();
    myQueue.push(u);//将节点放进去结果中
    for( int i =0;i<graph[u].size();i++){
        int t=graph[u][i];
        inDegree[t]--;
        if(inDegree[t]==0){
            node.push(t);
        }
        
    }
    
}
  return myQueue;
}

void _init( int m){
//完成的任务
int from ;
int to;

while(m--){
    cin>>from>>to;
    graph[from].push_back(to);
    inDegree[to]++;    
}

}

int main(){
 int n ,m;
 cin>>n>>m;
_init(m);
vector<int >result=TopSort(n);

return 0;
}

关键路径

/*
*   aov aoe
*  关键路径 最早发生时间&&最晚发生时间
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
#include<vector>
#include<algorithm>
#define MAXN 1000
using namespace std;
int  inDegree[MAXN]; // 定义入度
struct Edge
{
    int to;
    int length;
    Edge(int a, int b ):to(a),length(b);
    };
    queue<int>myQueue;// 求最短事件用的
    vector<Edge>graph[MAXN];
    int  earlyTime[MAXN]; //最早开始时间
    int lateTime[MAXN]; //最晚开始时间
    queue<int>TopQueue; //存储节点队列含有边的关系
    void _init( int m)  //边数
{
//完成节点的存储

}



void  TopSort( int n )   //返回一个最后事件的发生事件
{
    int lastTime;
  while(!myQueue.empty())
    {
        int a=myQueue.top();
        myQueue.pop();
        TopQueue.push(a);
        for(int i =0; i<graph[a].size(); i++)
        {
            int nodeNum=graph[a][i].to;
            int len=graph[a][i].length;
            if(earlyTime[a]+len>earlyTime[nodeNum])
            {
                earlyTime[a]+len=earlyTime[nodeNum];
                // 最早时间选择最大的
            }
            inDegree[nodeNum]--;
            if(inDegree[nodeNum]==0)
            {
                myQueue.push(nodeNum);
            }
        }
    }
    for( int j =TopQueue.size()-1; j>=0; j--)
    {
        //  一定是相反的顺序!
        int a =TopQueue[i];
        if(graph[a].size()==0){
            lateTime[a]=earlyTime[a];
        }
        for( int  k=0;k<graph[a].size()-1;k++){
            int  v=graph[u][j].to;
            int l=graph[u][j].length;
            lateTime[u]=min(lateTime[u],lateTime[v]-l);
            //  还少一个判断是不是关键路径的 
            
        }
    }
}

(部分代码 )

随笔

今天查阅资料时候发现servlet类似于spring mvc的一个地方 , 一般而言在写servlet时候 都是继承httpservlet, 利用httpservlet的service方法进而执行doGet或者doPost ,那么也可以自定义个servlet通过复写service方法识别url路径找到确定的字节码对象,进而找到对应的方法对象,执行方法

(这次操作真是惊到了我 真是万物皆对象 ,不由得让我想起了函数指针)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值