2015级计科软件《数据结构与算法》实践能力专题训练6图论

都存于小组成员练习题中

数据结构实验:连通分量个数

主要运用并查集的相关知识(不懂的可以学习一下)

#include 
#include 
#include 
#include 
using namespace std;

int b[1000];

int find(int x)
{
    while ( b[x] != x )
        x = b[x];
    return x;
}

void meget(int x, int y)
{
    int fx = find(x);
    int fy = find(y);
    if ( b[fx] != fy )
        b[fx] = fy;
}

int main()
{
    int T;
    int n, m, i, j;
    scanf ( "%d", &T );
    while ( T-- )
    {
        int h, h1;
        scanf ( "%d %d", &n, &m );
        for ( i = 1;i <= n; i++ )
            b[i] = i;
        for ( i = 0;i < m; i++ )
        {
            scanf ( "%d %d", &h, &h1 );
            meget(h, h1);
        }
        int sum = 0;
        for ( i = 1;i <= n; i++ )
        {
            if ( b[i] == i )
                sum++;
        }
        printf ( "%d\n", sum );
    }
    return 0;
}

图的深度遍历

顾名思义运用深搜

#include 
#include 
#include 
#include 
using namespace std;

bool ma[105][105];
bool vis[105];
int n, m;

void dfs(int x)
{
    int i;
    for ( i = 0;i < n; i++ )
    {
        if ( !vis[i] && ma[x][i] )
        {
            printf ( " %d", i );
            vis[i] = true;
            dfs(i);
        }
    }
}

int main()
{
    int x, y;
    int i, T;
    scanf ( "%d", &T );
    while ( T-- )
    {
        memset( ma, false, sizeof(ma) );
        memset( vis, false, sizeof(vis) );
        scanf ( "%d %d", &n, &m );
        for ( i = 0; i < m; i++ )
        {
            scanf ( "%d %d", &x, &y );
            ma[x][y] = true;
            ma[y][x] = true;
        }
        vis[0] = true;
        printf ( "0" );
        dfs(0);
        printf ( "\n" );
    }
    return 0;
}

树结构练习——判断给定森林中有多少棵树

还是并查集

#include 
#include 
#include 
#include 
using namespace std;

int b[1000];

int find(int x)
{
    while ( b[x] != x )
        x = b[x];
    return x;
}

void meget(int x, int y)
{
    int fx = find(x);
    int fy = find(y);
    if ( b[fx] != fy )
        b[fx] = fy;
}

int main()
{
    int n, m, i, j;
    while ( ~scanf ( "%d %d", &n, &m ) )
    {
        int h, h1;
        for ( i = 1;i <= n; i++ )
            b[i] = i;
        for ( i = 0;i < m; i++ )
        {
            scanf ( "%d %d", &h, &h1 );
            meget(h, h1);
        }
        int sum = 0;
        for ( i = 1;i <= n; i++ )
        {
            if ( b[i] == i )
                sum++;
        }
        printf ( "%d\n", sum );
    }
    return 0;
}

数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历

主要运用广搜

#include 
#include 
#include 
#include 
#include 
using namespace std;

int k;
bool vis[102];
bool ma[102][102];

void bfs(int x)
{
    int i;
    bool ok = false;
    queue q;
    q.push(x);
    vis[x] = true;
    while ( !q.empty() )
    {
        int temp = q.front();
        if ( !ok )
        {
            ok = !ok;
            printf ( "%d", temp );
        }
        else
            printf ( " %d", temp );
        q.pop();
        for ( i = 0;i < k; i++ )
        {
            if ( ma[temp][i]&&!vis[i] )
            {
                q.push(i);
                vis[i] = true;
            }
        }
    }
}

int main()
{
    int t, m, i;
    int T;
    int x, y;
    scanf ( "%d", &T );
    while ( T-- )
    {
        memset( ma, false, sizeof(ma) );
        memset ( vis, false, sizeof(vis) );
        scanf ( "%d %d %d", &k, &m, &t );
        for ( i = 0;i < m; i++ )
        {
            scanf ( "%d %d", &x, &y );
            ma[x][y] = true;
            ma[y][x] = true;
        }
        bfs(t);
        printf ( "\n" );
    }
    return 0;
}

数据结构实验之图论二:基于邻接表的广度优先搜索遍历

还是广搜

#include 
#include 
#include 
#include 
#include 
using namespace std;

int n, m, t;
bool vis[105], book[105][105];

void bfs(int t)
{
    int i;
    queue q;
    q.push(t);
    vis[t] = true;
    while ( !q.empty() )
    {
        int temp = q.front();
        q.pop();
        for ( i = 0;i < n; i++ )
        {
            if ( !vis[i]&&book[temp][i] )
            {
                printf ( " %d", i );
                q.push(i);
                vis[i] = true;
            }
        }
    }
}

int main()
{
    int T;
    int i, j;
    int x, y;
    scanf ( "%d", &T );
    while ( T-- )
    {
        memset ( vis, false, sizeof(vis) );
        memset ( book, false, sizeof(book) );
        scanf ( "%d %d %d", &n, &m, &t );
        for ( i = 0;i < m; i++ )
        {
            scanf ( "%d %d", &x, &y );
            book[x][y] = true;
            book[y][x] = true;
        }
        printf ( "%d", t );
        bfs(t);
    }
}


AOE网上的关键路径

这个题可能是我花费时间最长的题了吧!还是技术不行啊!

这个题你想用AOE麻烦死你,想用最短路(寻找最长路)的方法你也要选对了方式要不就超时了!

所以根本不能用Dijkstra算法、Bellman-Ford算法更别想用三层循环的Floyd-Warshall算法了!

因为以上算法我都试过都超时了。。。。所以就只能用优化队列形式的Bellman-Ford算法(SPEA)

这里要记下前驱所以我们要从终点到起点建立一个联系存最长路经过的点(这里我用的是book[])。

#include 
#include 
#include 
#include 
#include 
using namespace std;

const int N = 50010;
const int inf = (1<<20);
struct node
{
    int dist;
    int to;
    int next;
}E[3*N];
int top, xx, yy, n, m;
bool bookx[N], booky[N], vis[N];
int head[N], dis[N], book[N];

void init()
{
    int i;
    for ( i = 1;i <= n; i++ )
        book[i] = inf;
    memset ( head, -1, sizeof(head) );
    memset ( bookx, false, sizeof(bookx) );
    memset ( booky, false, sizeof(booky) );
    top = 0;
}

void Point()
{
    int i;
    for ( i = 1;i <= n; i++ )
    {
        if ( !bookx[i] )
            xx = i;
        if ( !booky[i] )
            yy = i;
    }
}

void SPEA()
{
    int i;
    for ( i = 1;i <= n; i++ )
    {
        dis[i] = inf;
        vis[i] = false;
    }
    vis[yy] = true;
    dis[yy] = 0;
    queue q;
    q.push(yy);
    while ( !q.empty() )
    {
        int u = q.front();
        q.pop();
        vis[u] = false;

        for ( i = head[u];i != -1; i = E[i].next )
        {
            int v = E[i].to;
            if ( dis[v] >= inf||dis[v] < dis[u]+E[i].dist )
            {
                dis[v] = dis[u]+E[i].dist;
                book[v] = u;
                if ( !vis[v] )
                {
                    vis[v] = true;
                    q.push(v);
                }
            }
            else if ( dis[v] == dis[u]+E[i].dist&&book[v] > u )
                book[v] = u;
        }
    }
}

int main()
{
    int i, j;
    int u, v, dist;
    while ( ~scanf ( "%d %d", &n, &m ) )
    {
        init();
        for ( i = 0;i < m; i++ )
        {
            scanf ( "%d %d %d", &u, &v, &dist );
            booky[u] = true;
            bookx[v] = true;
            E[top].to = u;
            E[top].dist = dist;
            E[top].next = head[v];
            head[v] = top++;
        }
        Point();
        SPEA();
        printf ( "%d\n", dis[xx] );
        i = xx;
        while ( i != yy )
        {
            printf ( "%d %d\n", i, book[i] );
            i = book[i];
        }
    }
    return 0;
}

数据结构实验之图论四:迷宫探索

用深搜的方式

#include 
#include 
#include 
#include 
#include 
using namespace std;

int n;
bool vis[1002];
bool ma[1002][1002];
int book[1002];
int sum;

void dfs(int x)
{
    int i;
    book[sum++] = x;
    vis[x] = true;
    for ( i = 1;i <= n; i++ )
    {
        if ( !vis[i]&&ma[x][i] )
        {
            dfs(i);
            book[sum++] = x;
        }
    }
}

int main()
{
    int T, s;
    int x, y;
    int m, i;
    scanf ( "%d", &T );
    while ( T-- )
    {
        sum = 0;
        memset( ma, false, sizeof(ma) );
        memset( vis, false, sizeof(vis) );
        scanf ( "%d %d %d", &n, &m, &s );
        for ( i = 0;i < m; i++ )
        {
            scanf ( "%d %d", &x, &y );
            ma[x][y] = true;
            ma[y][x] = true;
        }
        dfs(s);
        if ( sum == n*2-1 )
        {
            for ( i = 0; i < sum; i++ )
            {
                printf ( i != sum-1 ? "%d " : "%d\n", book[i] );
            }
        }
        else
        {
            for ( i = 0; i < sum; i++ )
            {
                printf ( "%d ", book[i] );
            }
            printf ( "0\n" );
        }
    }
    return 0;
}

数据结构实验之图论六:村村通公路

最小生成树

#include 
#include 
#include 
#include 
using namespace std;

struct node
{
    int x;
    int y;
    int dis;
};
int b[1002];

bool cmp ( node q, node p )
{
    return q.dis < p.dis;
}

int find( int x )
{
    while ( b[x] != x )
        x = b[x];
    return x;
}

bool meget( int x, int y )
{
    int fx = find(x);
    int fy = find(y);
    if ( fx != fy )
    {
        b[fx] = fy;
        return true;
    }
    return false;
}

int main()
{
    int n, m, i;
    while ( ~scanf ( "%d %d", &n, &m ) )
    {
        node a[6002];
        for ( i = 1;i <= n; i++ )
            b[i] = i;
        for ( i = 0;i < 2*m; i++ )
        {
            scanf ( "%d %d %d", &a[i].x, &a[i].y, &a[i].dis );
            a[i+1].x = a[i].y;
            a[i+1].y = a[i].x;
            a[i+1].dis = a[i].dis;
            i++;
        }
        sort ( a, a+2*m, cmp );
        int sum = 0;
        int cnt = 0;
        for ( i = 0;i < 2*m; i++ )
        {
            if ( meget(a[i].x, a[i].y) )
            {
                cnt++;
                sum = sum+a[i].dis;
                if ( cnt == n-1 )
                    break;
            }
        }
        if ( cnt == n-1 )
            printf ( "%d\n", sum );
        else
            printf ( "-1\n" );
    }
    return 0;
}
数据结构实验之图论七:驴友计划

Bell-Ford算法(主要改变是要用两个更新数组一个是距离dis[], 一个是钱数book[])

#include 
#include 
#include 
#include 
using namespace std;

const int inf = (1<<30);
struct node
{
    int x, y;
    int spend, len;
}a[400000];
int book[600];
int dis[600];

int main()
{
    int T, i, j;
    int n, m, x, y;
    scanf ( "%d", &T );
    while ( T-- )
    {
        scanf ( "%d %d %d %d", &n, &m, &x, &y );
        memset( book, 0, sizeof(book) );
        for ( i = 0;i < 2*m; i++ )
        {
            scanf ( "%d %d %d %d", &a[i].x, &a[i].y, &a[i].len, &a[i].spend );
            i++;
            a[i].x = a[i-1].y;
            a[i].y = a[i-1].x;
            a[i].spend = a[i-1].spend;
            a[i].len = a[i-1].len;
        }
        for ( i = 0;i < n; i++ )
            dis[i] = inf;
        dis[x] = 0;
        int sum = 0;
        for ( i = 0;i < n-1; i++ )
        {
            for ( j = 0;j < 2*m; j++ )
            {
                if ( dis[a[j].y] > dis[a[j].x]+a[j].len )
                {
                    dis[a[j].y] = dis[a[j].x]+a[j].len;
                    book[a[j].y] = book[a[j].x]+a[j].spend;
                }
                else if ( dis[a[j].y] == dis[a[j].x]+a[j].len&&book[a[j].x]+a[j].spend < book[a[j].y] )
                {
                    book[a[j].y] = book[a[j].x]+a[j].spend;
                }
            }
        }
        printf ( "%d %d\n", dis[y], book[y] );
    }
    return 0;
}

数据结构实验之图论八:欧拉回路

在做这题之前我们首先要复习一下生成欧拉回路所需要的条件

判断欧拉回路是否存在的方法

有向图:图连通,所有的顶点出度=入度。且没有孤立点(没有入度出度是0的点)

无向图:图连通,所有顶点都是偶数度。且没有孤立点(没有入度出度是0的点)

这题很明显就是无向图

我们就要判断有没有点被孤立了,是不是都是偶数度,是不是图联通(这个要用我们学到的并查集)

#include 
#include 
#include 
#include 
using namespace std;

bool a[1005][1005];
int du[1005];
int book[1005];

int find(int x)
{
    while ( book[x] != x )
        x = book[x];
    return x;
}

void meget(int x, int y)
{
    int fx = find(x);
    int fy = find(y);
    if (fx != fy)
    {
        book[fx] = fy;
    }
}

int main()
{
    int T;
    int x, y;
    int n, m, i;
    scanf ( "%d", &T );
    while ( T-- )
    {
        memset( a, false, sizeof(a) );
        memset( du, 0, sizeof(du) );
        scanf ( "%d %d", &n, &m );
        for ( i = 1;i <= n; i++ )
            book[i] = i;
        for ( i = 1;i <= m; i++ )
        {
            scanf ( "%d %d", &x, &y );
            if ( !a[x][y] )
            {
                a[x][y] = a[y][x] = true;
                du[x]++;
                du[y]++;
            }
            meget(x, y);
        }

        int temp = 0;
        int sum = 0;
        for ( i = 1;i <= n; i++ )
        {
            if ( book[i] == i )
                sum++;
            if ( du[i]%2 != 0 )
            {
                temp = 2;
                break;
            }
        }
        if ( sum == 1&&temp == 0 )
            printf ( "1\n" );
        else
            printf ( "0\n" );
    }
}

代码菜鸟,如有错误,请多包涵!!!

如有帮助记得支持我一下,谢谢!!!




你可能感兴趣的:(小组成员,练习题)