zoukankan      html  css  js  c++  java
  • 新队员图论基础_【CSUST_12级训练】


    背景:2013/05/05 去农大水了下蓝桥,估计是去了就有奖,吸引学生参赛,任然被虐!!!
               2013/05/11 惨败于湘潭邀请赛。
              最近一直纠结与考研还是工作,六级一直又没过,荒废了一段时间,今天就来新生这儿水一下找点做题的心情 
         吧。
              无论是比赛还是平时训练,果断被12级的虐了Orz,努力不够+。。。
        ID Origin Title
      4 / 7 Problem A HDU 1232 并查集
      3 / 4 Problem B HDU 1856 并查集
      1 / 3 Problem C HDU 1874 Floyd
      1 / 1 Problem D HDU 2544 Floyd || Dijkstra
        Problem E HDU 2066 Dijkstra
        Problem F HDU 2112 map + Floyd

    畅通工程

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 21422    Accepted Submission(s): 11116


    Problem Description
    某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路? 
     

    Input
    测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。 
    注意:两个城市之间可以有多条道路相通,也就是说
    3 3
    1 2
    1 2
    2 1
    这种输入也是合法的
    当N为0时,输入结束,该用例不被处理。 
     

    Output
    对每个测试用例,在1行里输出最少还需要建设的道路数目。 
     

    Sample Input
    4 2 1 3 4 3 3 3 1 2 1 3 2 3 5 2 1 2 3 5 999 0 0
     

    Sample Output
    1 0 2 998
    Hint
    Hint
    Huge input, scanf is recommended.
     

    Source
     

    Recommend
    JGShining
    A Accepted 232 KB 15 ms C++ 720 B 2013-05-23 19:20:32

    #include<stdio.h>
    
    const int maxn = 1000+10;
    int f[maxn];
    
    int find(int x)
    {
        return x == f[x] ? x : f[x] = find(f[x]);
    }
    
    void Union(int x, int y)
    {
        int fx = find(x);
        int fy = find(y);
        if(fx == fy) return;
        f[fx] = fy;
    }
    int main()
    {
        int n,m;
        while(scanf("%d", &n) != EOF)
        {
            if(n == 0) break;
            scanf("%d", &m);
    
            for(int i = 0; i <= n; i++)
            {
                f[i] = i;
            }
    
            int u, v;
            while(m--)
            {
                scanf("%d%d", &u, &v);
                Union(u, v);
            }
    
            int root = -1;
            for(int i = 1; i <= n; i++)
            {
                if(f[i] == i) root++;
            }
            printf("%d\n", root);
        }
        return 0;
    }
    

    More is better

    Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 327680/102400 K (Java/Others)
    Total Submission(s): 8956    Accepted Submission(s): 3346


    Problem Description
    Mr Wang wants some boys to help him with a project. Because the project is rather complex, the more boys come, the better it will be. Of course there are certain requirements.

    Mr Wang selected a room big enough to hold the boys. The boy who are not been chosen has to leave the room immediately. There are 10000000 boys in the room numbered from 1 to 10000000 at the very beginning. After Mr Wang's selection any two of them who are still in this room should be friends (direct or indirect), or there is only one boy left. Given all the direct friend-pairs, you should decide the best way.
     

    Input
    The first line of the input contains an integer n (0 ≤ n ≤ 100 000) - the number of direct friend-pairs. The following n lines each contains a pair of numbers A and B separated by a single space that suggests A and B are direct friends. (A ≠ B, 1 ≤ A, B ≤ 10000000)
     

    Output
    The output in one line contains exactly one integer equals to the maximum number of boys Mr Wang may keep. 
     

    Sample Input
    4 1 2 3 4 5 6 1 6 4 1 2 3 4 5 6 7 8
     

    Sample Output
    4 2
    Hint
    A and B are friends(direct or indirect), B and C are friends(direct or indirect), then A and C are also friends(indirect). In the first sample {1,2,5,6} is the result. In the second sample {1,2},{3,4},{5,6},{7,8} are four kinds of answers.
     

    Author
    lxlcrystal@TJU
     

    Source
     

    Recommend
    lcy

    B Accepted 78584 KB 328 ms C++ 781 B 2013-05-23 19:38:18

    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    const int maxn =  10000000+10;
    
    int p[maxn];
    int r[maxn];
    
    int find(int x)
    {
        return x == p[x] ? x : p[x] = find(p[x]);
    }
    
    void Union(int x, int y)
    {
        int fx = find(x);
        int fy = find(y);
        if(fx == fy) return;
    
        p[fx] = fy;
        r[fy] += r[fx];
    }
    
    void set()
    {
        for(int x = 0; x < maxn; x++)
        {
            p[x] = x;
            r[x] = 1;
        }
    }
    
    int main()
    {
        int n;
        while(scanf("%d", &n) != EOF)
        {
            set();
            int x, y;
            while(n--)
            {
                scanf("%d%d", &x, &y);
                Union(x, y);
            }
    
            int ans = 0;
            for(int i = 0; i < maxn; i++)
            {
                ans = max(ans,r[i]);
            }
    
            printf("%d\n", ans);
        }
        return 0;
    }

    畅通工程续

    Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 18225    Accepted Submission(s): 6299


    Problem Description
    某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。

    现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
     

    Input
    本题目包含多组数据,请处理到文件结束。
    每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
    接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
    再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
     

    Output
    对于每组数据,请在一行里输出最短需要行走的距离。如果不存在从S到T的路线,就输出-1.
     

    Sample Input
    3 3 0 1 1 0 2 3 1 2 1 0 2 3 1 0 1 1 1 2
     

    Sample Output
    2 -1
     

    Author
    linle
     

    Source
     

    Recommend
    lcy
     
    C Accepted 312 KB 46 ms C++ 1003 B 2013-05-23 20:11:02
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 210;
    const int INF = 2000000+10;
    int n,m;
    
    int d[maxn][maxn];
    
    void floyd()
    {
        for(int k = 0; k < n; k++)
        {
            for(int i = 0; i < n; i ++)
            {
                for(int j = 0; j < n; j++)
                {
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
                    //d[j][i] = d[i][j];//反正会遍历到,有没这句一样AC
                }
            }
        }
    }
    int main()
    {
        while(scanf("%d%d", &n,&m) != EOF)
        {
            for(int i = 0; i < n; i++)
            {
                for(int j = 0; j < n; j++)
                d[i][j] = (i == j ? 0 : INF);
            }
    
            int x, y, w;
            while(m--)
            {
                scanf("%d%d%d", &x, &y, &w);
                d[x][y] = min(d[x][y], w); //////
                d[y][x] = d[x][y];
            }
    
            floyd();
            int start,end;
            scanf("%d%d", &start,&end);
            if(d[start][end] == INF) printf("-1\n");
            else printf("%d\n", d[start][end]);
        }
        return 0;
    }
    

    C Accepted 316 KB 0 ms C++ 1136 B 2013-05-23 20:27:44
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 210;
    const int INF = 2000000+10;
    int map[maxn][maxn];
    int d[maxn];
    bool vis[maxn];
    
    int n,m;
    int start, end;
    
    void Dijkstra()
    {
        memset(vis, false, sizeof(vis));
        for(int i = 0; i < n; i++) d[i] = (i == start ? 0 : INF);
    
        for(int i = 0; i < n; i++)
        {
            int x, m = INF;
            for(int y = 0; y < n; y++) if(!vis[y] && d[y] <= m) m = d[x=y];
            vis[x] = true;
            for(int y = 0; y < n; y++) d[y] =  min(d[y], d[x]+map[x][y]);
        }
    }
    
    int main()
    {
        while(scanf("%d%d", &n,&m) != EOF)
        {
            for(int i = 0; i < n; i++)
            {
                for(int j = 0; j < n; j++)
                map[i][j] = (i == j ? 0 : INF);
            }
    
            int x, y, w;
            while(m--)
            {
                scanf("%d%d%d", &x, &y, &w);
                if(w < map[x][y])
                {
                    map[x][y] = w;
                    map[y][x] = w;
                }
            }
    
            scanf("%d%d", &start, &end);
            Dijkstra();
            if(d[end] == INF) printf("-1\n");
            else printf("%d\n", d[end]);
        }
        return 0;
    }
    

    最短路

    Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 20021    Accepted Submission(s): 8560


    Problem Description
    在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?

     

    Input
    输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
    输入保证至少存在1条商店到赛场的路线。
     

    Output
    对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
     

    Sample Input
    2 1 1 2 3 3 3 1 2 5 2 3 5 3 1 2 0 0
     

    Sample Output
    3 2
     

    Source
     

    Recommend
    lcy
     
    D Accepted 276 KB 31 ms C++ 892 B 2013-05-23 20:42:00
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 110;
    const int INF = 1000000+10;
    
    int d[maxn][maxn];
    int n,m;
    
    void floyd()
    {
        for(int k = 1; k <= n; k++)
        {
            for(int i = 1; i <= n; i++)
            {
                for(int j = 1; j <= n; j++)
                {
                    d[i][j] = min(d[i][j], d[i][k]+d[k][j]);
                }
            }
        }
    }
    int main()
    {
        while(scanf("%d%d", &n, &m) != EOF)
        {
            if(n == 0) break;
    
            for(int i = 1; i <= n; i++)
            {
                for(int j = 1; j <= n; j++)
                d[i][j] = (i == j ? 0 : INF);
            }
    
            int x,y,w;
            while(m--)
            {
                scanf("%d%d%d", &x,&y,&w);
                if(w < d[x][y])
                {
                    d[x][y] = w;
                    d[y][x] = w;
                }
            }
    
            floyd();
            printf("%d\n", d[1][n]);
    
        }
        return 0;
    }

    D Accepted 276 KB 15 ms C++ 1055 B 2013-05-23 20:50:17
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 110;
    const int INF = 1000000+10;
    
    int map[maxn][maxn];
    int d[maxn];
    bool vis[maxn];
    int n,m;
    
    void Dijkstra()
    {
        memset(vis, false, sizeof(vis));
    
        for(int i = 1; i <= n; i++) d[i] = (i == 1 ? 0 : INF);
    
        for(int i = 0; i < n; i++)
        {
            int x,m = INF;
            for(int y = 1; y <= n; y++) if(!vis[y] && d[y] <= m) m = d[x=y];
            vis[x] = true;
            for(int y = 1; y <= n; y++) d[y] = min(d[y], d[x]+map[x][y]);
        }
    }
    int main()
    {
        while(scanf("%d%d", &n,&m) != EOF)
        {
            if(n == 0) break;
    
            for(int i = 1; i <= n; i++)
            {
                for(int j = 1; j <= n; j++)
                map[i][j] = (i == j ? 0 : INF);
            }
    
            int x,y,w;
            while(m--)
            {
                scanf("%d%d%d", &x,&y,&w);
                if(w < map[x][y])
                {
                    map[x][y] = w;
                    map[y][x] = w;
                }
            }
    
            Dijkstra();
            printf("%d\n", d[n]);
        }
        return 0;
    }


    E 题题解见下一篇博客 :hdu 2066 一个人的旅行【Dijkstra 12级新生训练—图论E】

    F 题题解见下下篇博客: 

    hdu 2112 Today【F - map + Floyd - 入门训练】

  • 相关阅读:
    JS字符串之字符方法
    JS数组之归并方法
    JS数组之迭代方法
    JS数组之位置方法
    JS数组之操作方法
    【Vue-入门笔记-3】
    【Vue-入门笔记-2】
    阿里靠什么武功秘籍渡过“双十一“的天量冲击
    CC++ --- 线性表-学生成绩管理系统
    TortoiseSVN 使用教程
  • 原文地址:https://www.cnblogs.com/freezhan/p/3219054.html
Copyright © 2011-2022 走看看