旅行商问题

旅行商问题

描述
Shrek是一个大山里的邮递员,每天负责给所在地区的n个村庄派发信件。但杯具的是,由于道路狭窄,年久失修,村庄间的道路都只能单向通过,甚至有些村庄无法从任意一个村庄到达。这样我们只能希望尽可能多的村庄可以收到投递的信件。

Shrek希望知道如何选定一个村庄A作为起点(我们将他空投到该村庄),依次经过尽可能多的村庄,路途中的每个村庄都经过仅一次,最终到达终点村庄B,完成整个送信过程。这个任务交给你来完成。

输入
第一行包括两个整数n,m,分别表示村庄的个数以及可以通行的道路的数目。

以下共m行,每行用两个整数v1和v2表示一条道路,两个整数分别为道路连接的村庄号,道路的方向为从v1至v2,n个村庄编号为[1, n]。

输出
输出一个数字,表示符合条件的最长道路经过的村庄数。

样例
Input

4 3
1 4
2 4
4 3
Output

3

限制
1 ≤ n ≤ 1,000,000

0 ≤ m ≤ 1,000,000

输入保证道路之间没有形成环

时间:2 sec

空间:256 MB

提示
拓扑排序

#include <iostream>
#include <stdio.h>
#include<malloc.h>
using namespace std;

const int Maxlength = 100005;

typedef struct EdgeNode//边表节点的结构体
{
    int adjvex;//表示该边的另一个节点对应的下标
    //int weight;//保存该边的权值,无权图可以设为1
    struct EdgeNode *next;//指针域,指向下一个节点
} EdgeNode;
//----------------------------------------------------------------------------
typedef struct VertexNode//顶点表节点
{
    int data;//顶点域,存储顶点信息
    EdgeNode *firstedge;//指针域,指向邻接的第一个顶点
} VertexNode;
//----------------------------------------------------------------------------
typedef struct AdjList_Graph//用邻接表存储的图的结构体
{
    VertexNode adjlist[Maxlength];//存放顶点域和指针域

    int Vnum,Enum;//顶点数和边数,在本案例中未用到边数
} AdjList_Graph;
typedef struct Stack
{
    int data[Maxlength];
    int top;
} Stack;

int Roads[Maxlength];
int number=1;
int Indegree[Maxlength];

int LocateGraph(AdjList_Graph a,int data)
{
    for(int i = 0; i<a.Vnum; i++)
    {
        if(data == a.adjlist[i].data)
        {
            return i;//返回的是下标
        }
    }
}

void CreateAdjList(AdjList_Graph &G)//创建邻接表
{
    for(int i =0; i<G.Vnum; i++)
    {
        G.adjlist[i].data = i+1;
        G.adjlist[i].firstedge = NULL;
    }

    int FirstPoint,SecondPoint,FirstPosition,SecondPosition;

    for(int i=0; i<G.Enum; i++)
    {
        cin>>FirstPoint;

        cin>>SecondPoint;

        FirstPosition = FirstPoint-1;
        SecondPosition =SecondPoint-1;

        EdgeNode *e = (EdgeNode*)malloc(sizeof(EdgeNode));//向内存申请空间

        e->adjvex = SecondPosition;
        //e->weight = 1;
        e->next = NULL;//该表节点暂时没有下一个节点
        EdgeNode *p = G.adjlist[FirstPosition].firstedge;//将第FPS个顶点的边表头指针赋值给表节点指针p

        e->next = G.adjlist[FirstPosition].firstedge;
        G.adjlist[FirstPosition].firstedge = e;
//        if(p == NULL)//第FPS个顶点的边表结点为空
//        {
//            G.adjlist[FirstPosition].firstedge = e;//实现两点相连
//        }
//        else
//        {
//            while(p->next!=NULL)
//            {
//                p=p->next;
//            }
//            p->next=e;
//        }

        Indegree[SecondPosition]++;
    }
}

int isEmpty(Stack *s)
{
    if(s->top == -1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void initStack(Stack *s)
{
    s->top = -1;
}

void push(Stack *s,int data)
{
    s->data[++s->top] = data;
}

void pop(Stack *s,int *data)
{
    *data = s->data[s->top--];
}

void tuopupaixv(AdjList_Graph *a)
{
    Stack s ;
    initStack(&s);

    for(int i =0; i<a->Vnum; i++)
    {
        Roads[i] = 1;
    }

    for(int i = 0; i<a->Vnum; i++)
    {
        if(Indegree[i] == 0)
        {
            push(&s,i);
        }
    }

    int position;

    while(!isEmpty(&s))
    {
        pop(&s,&position);

        EdgeNode *p = a->adjlist[position].firstedge;

        while(p)
        {
            if(--Indegree[p->adjvex] == 0)
            {
                push(&s,p->adjvex);
            }
            if(Roads[position]+1>Roads[p->adjvex])
            {
                Roads[p->adjvex] = Roads[position]+1;
            }
            if(number<Roads[p->adjvex])
            {
                number = Roads[p->adjvex];
            }
            p = p->next;
        }
    }
}
//void AdjList_DFS(AdjList_Graph Gr,int StartData)//基于邻接表,从给定顶点深度遍历整个图
//{
//    int position = StartData-1;
//    EdgeNode *p;
//
//    Visited[position] = 1;//访问过的设置为1
//    number++;
//    //cout<<"DFS:"<<Gr.adjlist[position].data<<" ";
//    p = Gr.adjlist[position].firstedge;
//    while(p)
//    {
//        if(Visited[p->adjvex]==0)
//        {
//            AdjList_DFS(Gr,Gr.adjlist[p->adjvex].data);
//        }
//        p = p->next;
//    }
//}

//void Display_AdjList_Graph(AdjList_Graph G)//输出显示邻接表
//{
//    EdgeNode *e;
//    cout<<"共有"<<G.Vnum<<"个顶点"<<endl;
//    for(int i=0; i<G.Vnum; i++)
//    {
//        cout<<G.adjlist[i].data<<" ";
//    }
//    cout<<endl;
//    for(int i=0; i<G.Vnum; i++)
//    {
//        e = G.adjlist[i].firstedge;
//        while(e!=NULL)
//        {
//            cout<<"["<<G.adjlist[i].data<<"->"<<G.adjlist[e->adjvex].data<<"]";
//            e = e->next;
//        }
//        cout<<endl;
//    }
//}


int main()
{
    //cout<<"请输入图的结点数和边数:";

    AdjList_Graph G;

    cin>>G.Vnum>>G.Enum;

    CreateAdjList(G);

    // Display_AdjList_Graph(G);

    // cout<<"输出完毕"<<endl;

    //AdjList_DFS(G,1);

    tuopupaixv(&G);

    cout << number << endl;

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值