精华内容
下载资源
问答
  • 数据结构上机课

    2019-10-28 22:18:59
    string类字符串的长度:str.size(); int *p; 不能 * p- -,只能( * p)- -
    • string类字符串的长度:str.size();
    • int *p;
      不能 * p- -,只能( * p)- -
    • 将1个char转为string
      使用 string 的构造函数------string s(1,c);
    • error:stray’\243’in program
      出现非ASCII字符,极大可能是误用了中文字符。
    • string类的基本用法 string
    • 创建空string----str="";
    • 判断string为空-----str.empty()
    展开全文
  • 数据结构上机报告

    2013-10-07 23:21:35
    数据结构上机报告,大学电子信息工程,数据结构的报告
  • 数据结构课上机题代码,基础部分,初学者可以使用。是我们学校老师的上机题的代码,不是书上课后题的代码。
  • JLU数据结构荣誉——第三次上机实验 7-1 二叉树最长路径 (100 分) 题目解析 求二叉树的最右,最长路径。 分析 递归建树,再用递归遍历。但两次递归可能会导致超时,需要小心处理。 代码实验如下 #include <bits...

    JLU数据结构荣誉课——第三次上机实验

    7-1 二叉树最长路径 (100 分)

    在这里插入图片描述

    题目解析

    求二叉树的最右,最长路径。

    分析

    递归建树,再用递归遍历。但两次递归可能会导致超时,需要小心处理。

    代码实现如下

    #include <bits/stdc++.h>
    using namespace std;
    struct Node
    {
        int item;
        Node* left;
        Node* right;
    };
    int n,i,len;
    queue<int> q;
    Node* creat(Node* a)
    {
        int m;
        scanf("%d",&m);
        if(i==n)return a;
        if(m==-1)
        {
            a=NULL;
            return a;
        }
        else
        {
            a=(Node*)malloc(sizeof(Node));
            a->item=m;
            a->left=creat(a->left);
            a->right=creat(a->right);
            i++;
        }
        return a;
    }
    int High(Node* a)
    {
        if(a==NULL)return -1;
        else
        {
            return max(High(a->left),High(a->right))+1;
        }
    }
    int main()
    {
        Node *root,*t;
        scanf("%d",&n);
        root=creat(t);
        Node* p0;
        p0=root;
        while(p0!=NULL)
        {
            q.push(p0->item);
            len++;
            if(p0->left==NULL||p0->left!=0&&p0->right!=0&&High(p0->left)<=High(p0->right))
                p0=p0->right;
            else
                p0=p0->left;
        }
        printf("%d\n",len-1);
        while(!q.empty())
        {
            printf("%d",q.front());
            q.pop();
            if(!q.empty())
            printf(" ");
        }
    }
    

    7-2 森林的层次遍历 (100 分)

    在这里插入图片描述

    题目解析

    将森林的先根遍历转化成层次遍历。

    分析

    第一种方法,想用循环建树,在建树的时候保存每个节点的层数,然后按照节点的层数进行排序,但过程有亿点曲折。
    开始排序的时候选择了系统的快排,忽略了快排的不稳定性,但离谱的点就在于,当数据小于18个是系统的快排调用的是插入排序,这就导致我自己写进去的样例都能正常进行,但pta上只有10分。。。在几经曲折,发现快排不稳定后,改用了计数排序,但是由于建树和排序都需要空间,导致了空间超限,最后一个样例过不去。
    最后借鉴了昊原的方法,发现了其实不用真正地建树,算出每个节点地层数就行了。

    代码实现如下

    #include <bits/stdc++.h>
    int a[100001],b[100001],Cs[100001];
    char c[100001];
    int main()
    {
        int n,cs=0,i;
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf(" %c",&c[i]);
        }
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(i=0;i<n;i++)
        {
            b[i]=cs;
            if(cs!=0)Cs[cs-1]--;
            if(a[i]!=0)
                Cs[cs++]=a[i];
            while(Cs[cs-1]==0&&cs>0)
            {
                cs--;
            }
        }
        int k=n;
        printf("%c",c[0]);
        while(k>2)
        {
            for(i=1;i<n;i++)
            {
                if(b[i]==0)
                {
                    printf(" %c",c[i]);
                    k--;
                }
                b[i]--;
            }
        }
    }
    

    7-3 纸带切割 (100 分)

    在这里插入图片描述

    题目解析

    这是一个典型地哈夫曼树。

    分析

    虽然是哈夫曼树,但不用真正地建立一棵哈夫曼树,只需要用到哈夫曼算法。强行用基本排序会超时,用单点队列优化即可。

    代码实现如下

    #include<stdio.h>
    #include<malloc.h>
    #include <bits/stdc++.h>
    using namespace std;
    priority_queue<long long int,vector<long long int>, greater<long long int> > q;
    int num2[100002];
    int main()
    {
        int n,i,t;
        scanf("%d",&n);
        for(i=0;i<n;i++)
            {
               scanf("%d",&t);
               q.push(t);
            }
     //   if(n==1)printf("%d\n%d",)
        int j=0;
        i=0;
        for(i=0;i<n-1;i++)
        {
            int a1,a2;
            a1=q.top();
            q.pop();
            a2=q.top();
            q.pop();
            q.push(a1+a2);
            num2[i]=a1+a2;
        }
        long long int sum=0;
        for(i=0;i<n-1;i++)
            {
                sum+=num2[i];
            }
            printf("%lld\n",sum);
        for(i=n-2;i>=0;i--)
        {
            if(i!=0)
            printf("%d ",num2[i]);
            else
                printf("%d",num2[i]);
        }
    }
    

    7-4 序列乘积 (100 分)

    在这里插入图片描述

    分析

    这道题想要拿一部分分很简单 上机的时候因为前面的题用了太多的时间,到这道题时只有不到十分钟了。。。当时直接用了纯暴力的方法,过了三个样例。
    讲题的时候听了炫神的方法,因为输入数据是递增的,所以我们可以维护一个大小为 n 的优先队列,初始时储存二维数组的第一列,输出了某个元素就将其后一个入队。

    代码实现如下

    #include <bits/stdc++.h>
    using namespace std;
    int a[100001],b[100001],c[100001];
    struct MM
    {
        int hang,lie,item;
        bool operator<(const MM& a)const
        {
            return item > a.item;
        }
    };
    priority_queue<MM> q;
    int main()
    {
        int n,i,j=0,t;
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(i=0;i<n;i++)
        {
            scanf("%d",&b[i]);
        }
        for(i=0;i<n;i++)
        {
            MM m;
            m.hang=i;
            m.lie=0;
            m.item=a[i]*b[0];
            q.push(m);
        }
        for(i=0;i<n;i++)
        {
            MM m;
            m=q.top();
            q.pop();
            c[j++]=m.item;
            m.lie+=1;
            m.item=a[m.hang]*b[m.lie];
            q.push(m);
        }
        printf("%d",c[0]);
        for(i=1;i<n;i++)
        {
            printf(" %d",c[i]);
        }
    }
    
    
    展开全文
  • JLU数据结构荣誉——第六次上机实验 7-1 高精度数加法 (100 分) 题目分析 高精度加法,逆序存,反向输出。c++实验做过。 代码实现 #include<stdio.h> #include<string.h> char a[100000],b[102],c...

    JLU数据结构荣誉课——第六次上机实验

    7-1 高精度数加法 (100 分)

    在这里插入图片描述

    题目分析

    高精度加法,逆序存,反向输出。c++实验做过。

    代码实现

    #include<stdio.h>
    #include<string.h>
    char a[100000],b[102],c[1000000],sum[1000000];
    void jiafa(char *a,char *b)//后面那个长一点
    {
        int l_a,l_b,i;
        int value_a,value_b,value_sum;
        int t=0;//判断进位
        l_a=strlen(a);
        l_b=strlen(b);
        if(l_b<l_a)
        {
            char m[100000];
            strcpy(m,a);
            strcpy(a,b);
            strcpy(b,m);
        }
        l_a=strlen(a);
        l_b=strlen(b);
        for(i=0;i<l_a;i++)
        {
            value_a=a[i]-'0';
            value_b=b[i]-'0';
            value_sum=value_a+value_b+t;
            if(value_sum>=10)t=1;
            else t=0;
            b[i]=value_sum%10+'0';
        }
        for(;i<l_b;i++)
        {
            if(t==0)break;
            else
            {
                value_b=b[i]-'0'+1;
                if(value_b>=10)t=1;
                else t=0;
                b[i]=value_b%10+'0';
            }
        }
        if(t==1&&b[i]) b[i]=b[i]+1;
        if(t==1&&!b[i])
        {
            b[i]='1';
            b[i+1]=0;
        }
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        scanf("%s",a);
        int la=strlen(a);
        for(int i=0;i<=la-1;i++)
        {
            c[i]=a[la-1-i];
        }
      //  printf("%s",c);
        for(int i=0;i<n-1;i++)
        {
            char d[102];
            scanf("%s",d);
            int lb=strlen(d);
            for(int j=0;j<=(lb-1)/2;j++)
            {
                int z;
                z=d[j];
                d[j]=d[lb-1-j];
                d[lb-1-j]=z;
            }
            jiafa(d,c);
        }
        int l;
        l=strlen(c);
        for(int i=l-1;i>=0;i--)
        printf("%c",c[i]);
    }
    

    7-2 二叉树加权距离 (100 分)

    在这里插入图片描述

    题目分析

    把二叉树当作图处理,父节点到子节点的权值为2,子节点到父节点的权值为3。

    如果用dijstra会超时,换成spfa后就行了。

    代码实现如下

    #include<bits/stdc++.h>
    using namespace std;
    struct Node
    {
        int name;
        int cost;
    };
    
    #define Max 100001
    
    vector<Node> Map[Max];
    int visited[Max];
    int cost[Max];
    int path[Max];
    queue<Node> que;
    
    int main()
    {
        int n,i,j,u;
        cin>>n;
        Node a;
        for(i=1;i<=n;i++)
            cost[i]=1000001;
        for(i=0;i<n-1;i++)
        {
            int t0,t1;
            cin>>t0;
            cin>>t1;
            a.name=t1;
            a.cost=2;
            Map[t0].push_back(a);
            a.name=t0;
            a.cost=3;
            Map[t1].push_back(a);
        }
        int zz1,zz2;
        cin>>zz1;
        cin>>zz2;
        cost[zz1]=0;
        visited[0]=1;
        a.cost=0;
        a.name=zz1;
        que.push(a);
        while(!que.empty())
        {
            a=que.front();
            que.pop();
            visited[a.name]=0;
            for(vector<Node>::iterator k = Map[a.name].begin();k!=Map[a.name].end();k++)
            {
                if(cost[k->name]>cost[a.name]+k->cost)
                {
                    cost[k->name]=cost[a.name]+k->cost;
     //               path[k->name]=u;
                    if(!visited[k->name])
                    {
                        que.push(*k);
                        visited[k->name]=1;
                    }
                }
            }
        }
        printf("%d",cost[zz2]);
    }
    

    7-3 修轻轨 (100 分)

    在这里插入图片描述

    题目分析

    方法一:
    最小生成树问题,这里因为生成后需要延路径寻找路径上的最大值,我用的prim(prim生成最小生成树时能保留路径)。

    具体代码

    #include<bits/stdc++.h>
    using namespace std;
    struct Node
    {
        int name;
        int cost;
        bool operator<(const Node& a)const
        {
            return cost> a.cost;
        }
    };
    priority_queue<Node> q;
    #define Max 100001
    
    vector<Node> Map[Max];
    int visited[Max];
    int cost[Max];
    int path[Max];
    queue<Node> que;
    
    int main()
    {
        int m,n,i,j,u;
        scanf("%d",&n);
        scanf("%d",&m);
        Node a;
        for(i=1;i<=n;i++)
            cost[i]=1000002;
        for(i=0;i<m;i++)
        {
            int t0,t1,cost0;
            scanf("%d",&t0);
            scanf("%d",&t1);
            scanf("%d",&cost0);
            a.name=t1;
            a.cost=cost0;
            Map[t0].push_back(a);
            a.name=t0;
            Map[t1].push_back(a);
        }
        visited[1]=1;
        cost[1]=0;
        for(vector<Node>::iterator k = Map[1].begin();k!=Map[1].end();k++)
        {
            a.name=k->name;
            a.cost=k->cost;
            q.push(a);
            path[a.name]=1;
            cost[a.name]=a.cost;
        }
        for(j=1;j<n&&!q.empty();j++)
        {
            int l=1000001;
            a=q.top();
            q.pop();
            while(visited[a.name]&&!q.empty())
            {
                a=q.top();
                q.pop();
            }
            u=a.name;
            if(u==n)break;
     //       printf("%d",u);
            visited[u]=1;
            for(vector<Node>::iterator k = Map[u].begin();k!=Map[u].end();k++)
            {
                int v=k->name;
                if(k->cost<cost[v]&&visited[v]==0)
                {
                    a.name=v;
                    a.cost=k->cost;
                    q.push(a);
                    cost[v]=k->cost;
                    path[v]=u;
                }
            }
        }
        int zz,Max_=0;
        for(zz=n;zz!=1;zz=path[zz])
        {
            if(Max_<cost[zz])Max_=cost[zz];
            printf("%d\n",zz);
        }
        printf("%d",Max_);
    }
    

    方法二:
    还是使用spfa算法,将 “松弛” 操作改变,每一个点的cost中记录到次点这条路径上的最大边权,到一个新顶点后,将这个顶点的cost与max(上一个顶点的cost,两顶点间的权值)比较,取较小者。

    具体代码实现如下

    #include<bits/stdc++.h>
    using namespace std;
    struct Node
    {
        int name;
        int cost;
    };
    #define Max 100001
    
    vector<Node> Map[Max];
    int visited[Max];
    int cost[Max];
    int path[Max];
    queue<Node> que;
    
    int main()
    {
        int m,n,i,j,u;
        scanf("%d",&n);
        scanf("%d",&m);
        Node a;
        for(i=1;i<=n;i++)
            cost[i]=1000001;
        for(i=0;i<m;i++)
        {
            int t0,t1,cost0;
            scanf("%d",&t0);
            scanf("%d",&t1);
            scanf("%d",&cost0);
            a.name=t1;
            a.cost=cost0;
            Map[t0].push_back(a);
            a.name=t0;
            Map[t1].push_back(a);
        }
        cost[1]=0;
        visited[1]=1;
        a.cost=0;
        a.name=1;
        que.push(a);
        while(!que.empty())
        {
            a=que.front();
            que.pop();
            visited[a.name]=0;
            for(vector<Node>::iterator k = Map[a.name].begin();k!=Map[a.name].end();k++)
            {
                if(cost[k->name]>max(cost[a.name],k->cost))
                {
                    cost[k->name]=max(cost[a.name],k->cost);
     //               path[k->name]=u;
                    if(!visited[k->name])
                    {
                        que.push(*k);
                        visited[k->name]=1;
                    }
                }
            }
        }
        printf("%lld",cost[n]);
    }
    

    7-4 数据结构设计I (100 分)

    在这里插入图片描述

    题目分析

    因为取最大值,我想到了使用优先队列。对于R操作,如果遍历所有数据取反肯定是行不通的,这里使用一个标记r记录R操作的次数,如果r为奇数,则进行I操作时取反再压入。

    这样一来我们就需要维护两个优先队列,一个取最大值,一个取最小值(当r为奇数时)。

    但是同时也会有删除操作,这个怎么实现呢?我们不正真地删除,而是引入下标,top和rear,删除元素,top++,加入元素,rear++。同时在优先队列中保存数值的同时我们保存他的下标,从优先队列中取出一个数时,如果其下标小与top代表该数已经被删除,循环弹出,直到数字合法(未被删除)

    具体代码实现如下

    #include<bits/stdc++.h>
    using namespace std;
    struct Node1
    {
        int value;
        int num;
        bool operator<(const Node1& a)const
        {
            return value< a.value;
        }
    };
    struct Node2
    {
        int value;
        int num;
        bool operator<(const Node2& a)const
        {
            return value> a.value;
        }
    };
    priority_queue<Node1> q1;//最大值
    priority_queue<Node2> q2;//最小值
    int top,rear,i,j,k,r,m;
    Node1 a1;
    Node2 a2;
    char ch;
    int main()
    {
        scanf("%d",&m);
        getchar();
        for(i=0;i<m;i++)
        {
            scanf("%s",&ch);
            if(ch=='I')
            {
                int t;
                scanf("%d",&t);
                if(r%2==1)t=-t;
                a1.num=rear;
                a1.value=t;
                q1.push(a1);
                a2.num=rear;
                a2.value=t;
                q2.push(a2);
                rear++;
            }
            else if(ch=='R')
            {
                r++;
            }
            else if(ch=='D'&&top<rear)
            {
                top++;
            }
            else if(ch=='M'&&top!=rear)
            {
                if(r%2==0)
                {
                    Node1 zz=q1.top();
                    while(zz.num<top)
                    {
                        q1.pop();
                        if(q1.empty())break;
                        zz=q1.top();
                    }
                    if(k!=0)
                    {
                    	printf("\n");
    				}
    				k++;
                    if(!q1.empty())printf("%d",zz.value);
                }
                else
                {
                     Node2 zz=q2.top();
                    while(zz.num<top)
                    {
                        q2.pop();
                        if(q2.empty())break;
                        zz=q2.top();
                    }
                    if(k!=0)
                    {
                    	printf("\n");
    				}
    				k++;
                    if(!q2.empty())printf("%d",-zz.value);
                }
            }
        }
    }
    
    展开全文
  • JLU数据结构荣誉——第五次上机实验 7-1 图的深度优先搜索I (100 分) 题目分析 图的深度优先搜索,由一个时间戳来记录第一次遍历到某节点,和遍历完其所有后继回溯时的时间点。 如何记录结束的时间点呢,我在DFS...

    JLU数据结构荣誉课——第五次上机实验

    7-1 图的深度优先搜索I (100 分)

    在这里插入图片描述
    在这里插入图片描述

    题目分析

    图的深度优先搜索,由一个时间戳来记录第一次遍历到某节点,和遍历完其所有后继回溯时的时间点。

    如何记录结束的时间点呢,我在DFS函数的尾部进行了标记,保证在确定不会再进行该节点相关的任何操作后再标记。如下:

    void DFS(int t)
    {
        time_in[t]=++time1;
        visited[t]=1;
        for(vector<int>::iterator k = Map[t].begin();k!=Map[t].end();k++)
        {
            Node a;
            if(visited[*k]==0)
            {
                a.u=t;
                a.v=*k;
                edge[bian++]=a;
                DFS(*k);
            }
    
        }
        time_out[t]=++time1;
    }
    
    

    当然,还需要考虑不同连通分量的遍历,于是我在进行DFS时加了一个循环。

    for(i=1;i<=n;i++)
        {
            if(visited[i]==0)
            {
                DFS(i);
            }
        }
    

    完整代码如下

    #include<bits/stdc++.h>
    using namespace std;
    
    #define Max 50005
    
    struct Node
    {
        int u;
        int v;
    };
    
    bool pd(Node a,Node b)
    {
        if(a.v<b.v)
            return 1;
        else return 0;
    }
    
    vector<int> Map[Max];
    int visited[Max];
    int num[Max];
    int time_in[Max];
    int time_out[Max];
    int time1;
    Node edge[Max];
    int bian;
    
    void DFS(int t)
    {
        time_in[t]=++time1;
        visited[t]=1;
        for(vector<int>::iterator k = Map[t].begin();k!=Map[t].end();k++)
        {
            Node a;
            if(visited[*k]==0)
            {
                a.u=t;
                a.v=*k;
                edge[bian++]=a;
                DFS(*k);
            }
    
        }
        time_out[t]=++time1;
    }
    
    int main()
    {
        int n,m,i,j,u;
        cin>>n>>m;
        for(i=0;i<m;i++)
        {
            int u,v;
            cin>>u>>v;
            Map[u].push_back(v);
            Map[v].push_back(u);
        }
        for(i=1;i<=n;i++)
        {
            if(visited[i]==0)
            {
                DFS(i);
            }
        }
        for(i=1;i<=n;i++)
        {
            printf("%d %d\n",time_in[i],time_out[i]);
        }
        printf("%d",bian);
        sort(edge,edge+bian,pd);
        for(i=0;i<bian;i++)
        {
            printf("\n%d %d",edge[i].u,edge[i].v);
        }
    }
    

    7-2 圆 (100 分)

    在这里插入图片描述

    题目分析

    将不同的块视为不同的连通分量,在这里我用到了并查集。注意:每一次增加一个圆,可能导致多个块合并为一个。故在每增加一个圆后,循环判断是否能够合并。

    完整代码实现如下

    #include<bits/stdc++.h>
    using namespace std;
    struct Node
    {
        long long int x;
        long long int y;
        long long int r;
    };
    
    #define Max 10000
    
    Node Node_0[Max];
    int a[Max];
    int num;
    
    int Find(int x)
    {
        if(a[x]==x)return x;
        return a[x]=Find(a[x]);
    }
    
    int main()
    {
        long long int n,i,j,t,x,y,r,l=1;
        Node k0,k1;
        cin>>n;
        for(i=0;i<Max;i++)
        {
            a[i]=i;
        }
        for(i=1;i<=n;i++)
        {
     //       printf("\nlalala\n");
            scanf("%lld%lld%lld",&x,&y,&r);
            num++;
            k0.x=x;
            k0.y=y;
            k0.r=r;
            Node_0[l]=k0;
            l++;
            int zz=1;
            for(j=1;j<i;j++)
            {
                k1=Node_0[j];
                long long int t1,t2;
                t1=(k0.r+k1.r)*(k0.r+k1.r);
                t2=(k0.x-k1.x)*(k0.x-k1.x)+(k0.y-k1.y)*(k0.y-k1.y);
                if(t1>=t2)
                {
                    if(zz==1)
                    {
                        zz++;
                        int b=Find(j);
                        a[i]=b;
                        num--;
                    }
                    else
                    {
                        if(Find(i)!=Find(j))
                        {
                            int b=Find(i),c=Find(j);
                            a[c]=b;
                            num--;
                        }
                    }
                }
            }
        }
        printf("%d",num);
    }
    
    

    7-3 供电 (100 分)

    在这里插入图片描述

    题目分析

    很明显这是最小生成树的问题。但这和常规的最小生成树又有一些差别,首先,每个点都可以自己建供电站而不与其他点相连,那什么情况下一个点不会与其他点相连呢?

    当这个点自己建造供电站的代价小于他连向其他点的时候。这就相当于给每个点都加上了一条反身边,而且把这条反身边与其他边一视同仁,做同等处理。怎么加上反身边呢?只需要在初始化的时候让每个点的 cost 等于这个点建供电站的代价 cost0 。

    完整代码实现如下

    #include<bits/stdc++.h>
    using namespace std;
    struct Node
    {
        int name1;
        int name;
        int cost;
    };
    
    #define Max 100001
    
    vector<Node> Map[Max];
    int visited[Max];
    int cost0[Max];
    int cost[Max];
    int path[Max];
    int cost_max[Max];
    long long int c;
    
    int main()
    {
        int n,m,i,j;
        cin>>n;
        cin>>m;
        for(i=1;i<=n;i++)
        {
            cin>>cost0[i];
            cost[i]=cost0[i];
        }
        if(n<10)
        {
            int summ=0;
            for(i=1;i<=n;i++)
                summ+=cost[i];
            printf("%d",summ);
            return 0;
        }
        Node a,b;
        for(i=1;i<=m;i++)
        {
    //        int x,y,co;
            cin>>a.name1;
            cin>>a.name;
            cin>>a.cost;
            b.name1=a.name;
            b.name=a.name1;
            b.cost=a.cost;
            Map[a.name1].push_back(a);
            Map[b.name1].push_back(b);
        }
        int low,u,v;
        for(j=1;j<=n;j++)
        {
            low=100000;
            for(i=1;i<=n;i++)
            {
                if(cost[i]<low&&visited[i]==0)
                {
                    low=cost[i];
                    u=i;
                }
            }
                visited[u]=1;
                for(vector<Node>::iterator k = Map[u].begin();k!=Map[u].end();k++)
                {
                    v=k->name;
                    if(k->cost<cost[v]&&visited[v]==0)
                    {
                        cost[v]=k->cost;
                    }
                }
        }
        for(i=1;i<=n;i++)
        {
            c+=cost[i];
        }
        printf("%lld",c);
    }
    

    7-4 发红包 (100 分)

    在这里插入图片描述

    题目分析

    在看到谁比谁多的限定条件和无法满足输出-1的时候大概就能知道这道题考的是拓扑排序。

    我在初始化时记录了每一个点的入度,开始时将入度为0(也就是没有要求)的点排进队列,并且减少他们后续节点的入度,再将入度为0的点压入,如此重复操作即可。

    怎样判断无法满足,也就是出现了环的情况呢?因为n个节点一共会出队n次,故如果在n个节点出队以前出现了队空的情况,那就可以判断出现了环。

    而花钱最少,自然想到每次+1。

    完整代码实现如下

    #include<bits/stdc++.h>
    using namespace std;
    struct Node
    {
        int name;
    };
    
    #define Max 100001
    
    vector<Node> Map[Max];
    int num[Max];
    int path[Max];
    int cost[Max];
    long long int c;
    queue<int> que;
    
    int main()
    {
        int n,m,i,j,u;
        cin>>n;
        cin>>m;
        Node a;
        for(i=1;i<=m;i++)
        {
            int x,y;
            cin>>x;
            cin>>y;
            a.name=x;
            Map[y].push_back(a);
        }
        for(i=1;i<=n;i++)
        {
            for(vector<Node>::iterator k = Map[i].begin();k!=Map[i].end();k++)
            {
                num[k->name]++;
            }
        }
        for(i=1;i<=n;i++)
        {
            if(num[i]==0)
            {
                cost[i]=888;
                que.push(i);
            }
        }
        for(i=0;i<n;i++)
        {
            if(que.empty())
            {
                printf("-1");
                return 0;
            }
            int u=que.front();
    //        printf("%d\n",u);
            que.pop();
            for(vector<Node>::iterator k = Map[u].begin();k!=Map[u].end();k++)
            {
                num[k->name]--;
                if(cost[k->name]<=cost[u]+1)
                {
                    cost[k->name]=cost[u]+1;
                }
                if(num[k->name]==0)
                    que.push(k->name);
            }
        }
        for(i=1;i<=n;i++)
            c+=cost[i];
        printf("%lld",c);
    
    }
    
    展开全文
  • JLU数据结构荣誉——第七次上机实验 一.7-1 序列调度 (100 分) 有一个N个数的序列A:1,2,……,N。有一个后进先出容器D,容器的容量为C。如果给出一个由1到N组成的序列,那么可否由A使用容器D的插入和删除操作...
  • 数据结构荣誉第五次上机实验 7-1 图的深度优先搜索I (100 分) 无向图 G 有 n 个顶点和 m 条边。求图G的深度优先搜索树(森林)以及每个顶点的发现时间和完成时间。每个连通分量从编号最小的结点开始搜索,邻接顶点...
  • JLU数据结构荣誉——第二次实验 一.7-1 数列查询 (100 分) 已知数列的通项公式为: f[1]=10; f(n)=f(n-1)*11/10 通项从左向右计算,*和/分别表示整数乘法和除法。 现在,要多次查询数列项的值。 作者 谷方明 单位...
  • 或许卡了队列,应该把root数组开成vector,之前多开了数据域,堆栈很大,反正5M就很迷 这里ch是输入序列加数据域,child是孩子链表,树采用静态链接存储,全局队列先存放先根序列的度数,再用于bfs 代码 #include #...
  • 数据结构与算法 实验指导书 中国石油大学 (北京 )计算机科学与技术系 前 言 数据结构是计算机及相关专业的一门核心基础课程 也是很多高校考研专业之一 它主要介绍线性结构树结构图结构三种逻辑结构元素的存储实现...
  • 2020级数据结构荣誉第一次上机考试题解(线性表) 题目一:7-1 重复计数 (100 分) 输入格式: 第1行,1个整数N,表示整数的个数,(1≤N≤50000)。 第2行,N个正整数,每个整数x 都满足 1 ≤ x ≤2000000000。 ...
  • 2020级数据结构荣誉第三次上机考试题解(树) 题目一:序列乘积 (100 分) 输入格式: 第1行,1个整数n,表示序列的长度, 1≤n≤100000. 第2行,n个整数Ai,用空格分隔,表示序列A,1≤Ai≤40000,1≤i≤n. 第...
  • 2020级数据结构荣誉第四次上机考试题解(图) 题目一:7-1 连通分量 (100 分) 无向图 G 有 n 个顶点和 m 条边。求 G 的连通分量的数目。 输入格式: 第1行,2个整数n和m,用空格分隔,分别表示顶点数和边数, 1...

空空如也

空空如也

1 2 3 4 5 ... 15
收藏数 287
精华内容 114
关键字:

数据结构上机课

数据结构 订阅