ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-06-02 23:00:11  阅读:141  来源: 互联网

标签:JLU Map 上机 int Max Node ++ cost 数据结构


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,Map,上机,int,Max,Node,++,cost,数据结构
来源: https://blog.csdn.net/qq_51416280/article/details/117486007

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有