回 帖 发 新 帖 刷新版面

主题:第52次编程比赛题目

(麻烦bm设置sticky)

天还亮着,看着不像晚上,不过就现在放出来吧,不拖了

给出一个简单无向图G=(V,E),图里面没有偶圈,对于其中指定的两个顶点u和v,计算从u到v的路径的数目。

解答用C或C++应该实现如下接口:

void solve(int n, int m, const int *e, int u, int v);

其中n=|V|即顶点数,m=|E|即边数。所有顶点按0,1,2...,n-1编号。e指向一个有2m个整数的数组,e[2*i]和e[2*i+1](i=0,1,2,...,m-1)表示一条边的两个端点。u,v就是两个指定的顶点。

允许编写其他函数。允许自行定义数据结构。只允许包含C或C++的标准库的头文件。请明确指定代码使用C还是C++编译。

solve和其他函数只允许向标准输出(stdout)输出数据。输出数据只能包括一行,这一行的内容只能包括用十进制表示的答案。答案前后不能有空格、Tab,不能有多余的前导0。

测试程序只包括一个文件,框架如下:

#include <stdio.h> /* C */
#include <cstdio> /* C++ */

/*
解答内容在此,包括solve函数
*/

int main(void)
{
    用scanf之类的东西读入n, m, e, u, v;
    solve(n, m, e, u, v);
    return 0;
}

提示:
1. (无向图就不解释了,各位翻翻课本吧。)简单图不包含自环和两条首尾相同的边。圈和路径都不包含重复顶点。偶圈就是长度是偶数(当然不能是0啦)的圈。
2. V和E的大小原则上没有特殊限制,以保持测试机器稳定运行和遵从内存限制为限。
3. 测试时,将会允许充分的内存空间,但是原则上栈空间不超过32M,总空间不超过256M。
4. 测试时,时间限制将参考一个Java程序的运行时间(解释语言啊,足够放水的了)。
5. 测试时,作为扩展要求,存在至少一组数据,unsigned __int64/long long存不下结果,做对的将有额外的优势。基本要求下unsigned __int64/long long都没有问题。
6. 测试时用的编译器是MinGW gcc/g++ 3.4.2。出现编译错的代码我原则上不会去修改。
7. 代码要求不能太乱,复杂的逻辑最好加上注释。如果代码因为非技术原因让我看不懂的话,很可能影响最后的评价。
8. 在保证正确性和程序可运行的前提下,请首先尽量降低算法的时间复杂度,其次才考虑运行效率。
9. 放水提示:考虑图的双连通分量。

回复列表 (共18个回复)

11 楼

哎呀,我看不懂呀。

12 楼

#include <stdio.h>
int count = 0;/*for the solutions*/
/*print the solutions*/
void printpath(int *p, int lenth)
{
    int i = 0;
    for(i = 0; i < lenth; i++)
        printf("%d->", p[i]);
    printf("%d", p[i]);
    printf("\n");
}
/*use the recursive way to resolve under the condition of u != v*/
void pathall(int n, int u, int v, int **matrix, int *temp, int *path, int lenth, int *visited)
{
    int node, i = 1;
    int j;

    visited[u] = 1;/*indicate that u has been visited*/
    lenth++;/*the lenth of path*/
    path[lenth] = u;
    if(u == v)/*find the path then print it*/
    {
        count++;
        printpath(path, lenth);
    }

    for(i = 1; i < temp[u]; i++)
    {
        node = matrix[u][i];
        if(visited[node] == 0)
            pathall(n, node, v, matrix, temp, path, lenth, visited);
    }

    visited[u] = 0;/*make u available for the next round*/
    lenth--;
}

void solve(int n, int m, const int *e, int u, int v)
{
    int i, j, *p;
    int **matrix; 
    int *temp, *path, *visited;
    int lenth = -1;

    visited = (int*)malloc(sizeof(int) * n);
    path = (int*)malloc(sizeof(int) * n);
    temp = (int*)malloc(sizeof(int) * n);
    for(i = 0; i < n; i++)
    {
        temp[i] = 1;
        path[i] = -1;
        visited[i] = 0;
    }
    /*apply enough memory to create the data structure for the list*/
    matrix = (int**)malloc(sizeof(int*) * n);
    for(i = 0; i < n; i++)
    {
        p = (int*)malloc(sizeof(int) * n);
        matrix[i] = p;
    }
    /*initialize the array list*/
    /*imitate the 2 dimensional array*/
    for(i = 0; i < n; i++)
       for(j = 0; j < n; j++)
           matrix[i][j] = 0;
    
    for(i = 0, j = 0; i < n; i++)
        matrix[i][j] = i;
    /*create the list*/
    for(i = 0; i < 2 * m - 1; i += 2)
    {
        matrix[e[i]][temp[e[i]]] = e[i + 1];
        temp[e[i]]++;
        matrix[e[i + 1]][temp[e[i + 1]]] = e[i];
        temp[e[i + 1]]++;
    }
    /*solution for under the condition u == v*/
    
    pathall(n, u, v, matrix, temp, path, lenth, visited);
    
    /*in case of memory leaks*/
    for(i = 0; i < n; i++)
        free(matrix[i]);
    free(matrix);
    free(temp);
    free(path);
}

int main(void)
{
    int i;
    int n, m, *e, u, v;

/*    freopen("in.txt", "r", stdin); *//*for convenience which is no use*/
    scanf("%d%d", &n, &m);
    e = (int*)malloc(sizeof(int) * m * 2);
    for(i = 0; i <= 2 * m -1; i+=2)
        scanf("%d%d", &e[i], &e[i + 1]);
    scanf("%d%d", &u, &v);
    solve(n, m, e, u, v);/*function required*/ 
    printf("%d\n",count);

    free(e);
    return 0;
}

13 楼


struct VNode{
    int mNo;
    VNode* mNext;
    VNode* mPrior;
};

class CVertex{
private:
    int mNo;        //顶点编号
    int mDegree;    //顶点度
    VNode* mHead;    //链表头
    VNode* mTail;    //链表尾
    VNode* mCur;    //当前访问的邻接点

public:
    CVertex(){
        mDegree = 0;
        mHead = new VNode;
        mTail = new VNode;
        
        mHead->mNext = mTail;
        mHead->mPrior = NULL;
        mTail->mNext = NULL;
        mTail->mPrior = mHead;

        SetCurHead();
    }

    ~CVertex(){
        while(mHead->mNext != mTail){
            mHead = mHead->mNext;
            delete mHead->mPrior;
        }
        delete mTail;
    }

    int GetDegree(){
        return mDegree;
    }

    void AddDegree(int No){
        VNode* vn = new VNode;
        vn->mNo = No;
        vn->mPrior = mTail->mPrior;
        mTail->mPrior->mNext = vn;
        mTail->mPrior = vn;
        vn->mNext = mTail;
        mDegree ++;
    }

    void DelDegree(int No){
        VNode *vn = mHead->mNext;
        while(vn->mNo != No)
            vn = vn->mNext;
        vn->mPrior->mNext = vn->mNext;
        vn->mNext->mPrior = vn->mPrior;
        delete vn;
        mDegree --;
    }

    VNode* GetCurNode(){
        return mCur;
    }

    void SetCurHead(){
        mCur = mHead;
    }

    bool SetCurNext(){
        if(mCur->mNext == mTail)
            return false;
        else
            mCur = mCur->mNext;
        return true;
    }
    
    void SetNo(int No){
        mNo = No;
    }

    void Show(){
        cout<<"  顶点编号:"<<mNo<<"  度:"<<mDegree<<"  相邻顶点:";
        VNode* vn = mHead;
        while(vn->mNext != mTail){
            vn = vn->mNext;
            cout<<vn->mNo<<"  ";
        }
        cout<<endl;
    }
};

14 楼

续上

class CGraph{
private:
    CVertex* mCV;
    int mn;
    int mu,mv;
    void MySet(int n,int u,int v){
        mn=n;
        mu=u;
        mv=v;
        mCV = new CVertex[n];
        for(int i=0;i<mn;i++)
            mCV[i].SetNo(i);
    }
    
    void ShowPath(int len,int *path)
    {
        cout<<"一条路径:";
        for(int i=0;i<=len;i++)
            cout<<path[i]<<"  ";
        cout<<endl;
    }
/*
    void youhua(){
    }
*/
public:
    CGraph(int n,int m,const int* e,int u,int v){
        MySet(n,u,v);
        for(int i=0;i<m;i++){
            mCV[e[i*2]].AddDegree(e[i*2+1]);
            mCV[e[i*2+1]].AddDegree(e[i*2]);
        }
    }

    CGraph(int n,int** Matrix,int u,int v){
        MySet(n,u,v);

    }

    ~CGraph(){
        delete []mCV;
    }
    
    void Show(){
        cout<<"\n\n  显示图:"<<"  顶点数:"<<mn<<endl;
        for(int i=0;i<mn;i++)
            mCV[i].Show();
        cout<<"\n求顶点 "<<mu<<" , "<<mv<<" 间的路径数"<<endl;
        cout<<"显示完毕!!"<<endl;
    }

    int solve();
};

int CGraph::solve()
{
    int *path = new int [mn];
    int len = 0;
    
    path[0] = mu;
    int paths = 0;
    do{
        if(!mCV[path[len]].SetCurNext()){//无路可走
            mCV[path[len]].SetCurHead();
            len --;
        }
        else{//路径的下一个顶点
            int tmp = mCV[path[len]].GetCurNode()->mNo;
            bool bGo = false;
            for(int i=0;i<=len;i++){
                if(path[i] == tmp){
                    bGo = true;
                    break;
                }
            }
            if (bGo)
                continue;
            len++;
            path[len] = tmp;
            if(path[len] == mv){//到达终点
//                ShowPath(len,path);
                paths ++;
                len --;
            }
        }
    }while(len>=0);
    return paths;
}
void solve(int n, int m, const int *e, int u, int v)
{
    CGraph cg(n,m,e,u,v);
    cg.Show();
    cout<<cg.solve()<<endl<<endl;
}

15 楼

/*
C 语言编译器编译
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define BASE 1000000000//10e9
#define SIZE 5

typedef struct
{
    int data;//用来存放顶点值(const int *e里的值)
    unsigned long routeNum[SIZE];//用来存放此点到源点的路径数
}POINT;

//大数乘2
void multiple(unsigned long *p)
{
    unsigned long temp = 0;
    int i = SIZE - 1;

    while (i >= 0)
    {
        temp += (2 * p[i]);
        if (temp > BASE)
        {
            p[i] = (temp % BASE);
            temp /= BASE;
        }
        else
        {
            p[i] = temp;
            break;
        }
        i--;
    }
}
//大数相加
void add(unsigned long *p, unsigned long *sum)
{
    unsigned long temp = 0;
    int i = SIZE - 1;

    while (i >= 0)
    {
        temp += (p[i] + sum[i]);
        if (temp > BASE)
        {
            sum[i] = (temp % BASE);
            temp  /= BASE;
        }
        else
        {
            sum[i] = temp;
            break;
        }
        i--;
    }
}
//显示大数
void print(unsigned long *p)
{
    int index = 0;
    while (p[index] == 0  &&  index < SIZE - 1)
    {
        index++;
    }
    
    printf("%u",p[index++]);

    while (index < SIZE)
    {
        if (p[index] < 10)
        {
            printf("00000000");
        }
        else if (p[index] < 100)
        {
            printf("0000000");
        }
        else if (p[index] < 1000)
        {
            printf("000000");
        }
        else if (p[index] < 10000)
        {
            printf("00000");
        }
        else if (p[index] < 100000)
        {
            printf("0000");
        }
        else if (p[index] < 1000000)
        {
            printf("000");
        }
        else if (p[index] < 10000000)
        {
            printf("00");
        }
        else if (p[index] < 100000000)
        {
            printf("0");
        }
        printf("%u",p[index++]);
    }
}
//判断num是否在pStore里面.若是返回其下标,否则-1
int in_POINT(int num, POINT *pStore, int stop)
{
    int i = 0;
    while (i < stop)
    {
        if (num == pStore[i++].data)
        {
            return i-1;
        }
    }
    return -1;
}
int in_found(int num, const int *pFound,int posStop)
{
    int i = 0;
    while (i < posStop)
    {
        if (num == pFound[i++])
        {
            return i-1;
        }
    }
    return -1;
}

int save_found(int unsave, const POINT *pStore, int storeStop, int *pFound, int foundStop)
{
    int i = 0;
    while (i < storeStop)
    {
        if (unsave != pStore[i].data)//unsave是不想存入的点
        {
            pFound[foundStop++] = pStore[i].data;
        }
        i++;
    }
    return foundStop;
}

16 楼

//edge中搜索store[storePos].data的邻接点,并将其信息存入temp中
int search_adjacency(const int *edge, int m, POINT *store, int storePos,
                     const int *pFound, int foundStop, POINT *temp, int v)
{
    int i = 0;
    int tempPos = 0;
    int index1, index2;

    while (i < m)//所有不在found中且与store[storePos]邻接的点都存入temp中
    {
        if (edge[2*i] == store[storePos].data)
        {
            if (in_found(edge[2*i+1],pFound,foundStop) == -1)
            {
                temp[tempPos].data = edge[2*i+1];
                memcpy(temp[tempPos++].routeNum, store[storePos].routeNum, 
                       SIZE*sizeof(unsigned long));
            }
        }
        if (edge[2*i+1] == store[storePos].data)
        {
            if (in_found(edge[2*i],pFound,foundStop) == -1)
            {
                temp[tempPos].data = edge[2*i];
                memcpy(temp[tempPos++].routeNum, store[storePos].routeNum, 
                       SIZE*sizeof(unsigned long));
            }
        }        
        i++;
    }

    for (i=0; i<m; i++)
    {
        if (edge[2*i] != v  &&  edge[2*i+1] != v)
        {
            index1 = in_POINT(edge[2*i],temp,tempPos);
            if (index1 != -1)
            {
                index2 = in_POINT(edge[2*i+1],temp,tempPos);
                if (index2 != -1)
                {
                    multiple(temp[index1].routeNum);
                    multiple(temp[index2].routeNum);
                }
            }
        }
    }
    return tempPos;
}

17 楼

void solve(int n, int m, const int *e, int u, int v)//题目确保u,v在图内,所以不判断
{
    if (u == v)
    {
        printf("\nnumbers of routes from %d to %d is: 0\n", u, v);;
        return ;
    }

    else
    {
        int *pFound = (int *)malloc(sizeof(int) * n);//用来记录已经访问过的点数
        int foundStop = 1;//pFound数组的停止的位置,因为u已知,所以从1开始.v是最后存入
        POINT *begin = (POINT *)malloc(sizeof(POINT) * (n-1));//记录从u出发所访问的邻接点
        POINT *temp = (POINT *)malloc(sizeof(POINT) * (n-1));//临时存放点,存完后拷到begin中
        int beginStop = 0, tempStop = 0;//begin,temp数组停止的位置
        int beginPos = 0;
        int i = 0;
        unsigned long sum[SIZE] = {0};//记录总的路径数

        memset(begin, 0, sizeof(POINT)*(n-1));
        memset(temp, 0, sizeof(POINT)*(n-1));

        pFound[0] = u;
        
        //搜索与u相邻的点,并将信息填入begin数组中
        while (i < m)
        {
            if (e[2*i] == u)
            {
                begin[beginPos].data = e[2*i+1];
                begin[beginPos++].routeNum[SIZE - 1] = 1;
            }
            if (e[2*i+1] == u)
            {
                begin[beginPos].data = e[2*i];
                begin[beginPos++].routeNum[SIZE - 1] = 1;
            }
            i++;
        }
        beginStop = beginPos;
        for (i=0; i<m; i++)
        {
            if (e[2*i] != v  &&  e[2*i+1] != v)//包含v的边不能*2
            {
                int index1 = in_POINT(e[2*i],begin,beginStop);
                if (index1 != -1)
                {
                    int index2 = in_POINT(e[2*i+1],begin,beginStop);
                    if (index2 != -1)
                    {
                        begin[index1].routeNum[SIZE - 1] = 2;
                        begin[index2].routeNum[SIZE - 1] = 2;
                    }
                }
            }
        }
        
        //判断v是否在begin中,在就记录总和,不在就将begin.data存入found中
        if ( (i = in_POINT(v,begin,beginStop)) != -1)
        {
            add(begin[i].routeNum,sum);
        }

        //将不是v的点存入found中
        foundStop = save_found(v,begin,beginStop,pFound,foundStop);

        //搜索与begin数组中相邻的点,并将信息填入temp.完后,将temp拷到begin中,开始下一次搜索
        while ( (foundStop < (n - 1))  &&  (beginStop != 0) )//found中最后一个元素是v,并且begin中有元素
        {
            for (beginPos=0; beginPos<beginStop; beginPos++)
            {
                if (begin[beginPos].data != v)//与v邻接的点不用计算
                {
                    tempStop += search_adjacency(e,m,begin,beginPos,pFound,
                                                 foundStop,temp+tempStop,v);
                }
            }
                
            //copy到begin中
            memcpy(begin,temp,tempStop*sizeof(POINT));
            beginStop = tempStop;
            tempStop  = 0;

            //判断v是否在begin中,在就记录总和,不在就将begin.data存入found中
            if ( (i = in_POINT(v,begin,beginStop)) != -1)
            {
                add(begin[i].routeNum,sum);
            }

            //将不是v的点存入found中
            foundStop = save_found(v,begin,beginStop,pFound,foundStop);
        }

        //释放资源,结束
        free(pFound);
        free(begin);
        free(temp);

        printf("num of routes from %d to %d is: ", u,v);
        print(sum);
        putchar('\n');
    }
}

int main(void)
{
    int e[16] = {0,1, 1,2, 2,0, 3,4, 4,5, 5,3, 2,3, 7,8};
    solve(8,8,e,2,3);
    return 0;
}

18 楼

到点了,嗯

我来回复

您尚未登录,请登录后再回复。点此登录或注册