• 2017中国大学生程序设计竞赛


    Deleting Edges

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
    Total Submission(s): 567    Accepted Submission(s): 210


    Problem Description
    Little Q is crazy about graph theory, and now he creates a game about graphs and trees.
    There is a bi-directional graph with  nodes, labeled from 0 to . Every edge has its length, which is a positive integer ranged from 1 to 9.
    Now, Little Q wants to delete some edges (or delete nothing) in the graph to get a new graph, which satisfies the following requirements:
    (1) The new graph is a tree with  edges.
    (2) For every vertice , the distance between 0 and  on the tree is equal to the length of shortest path from 0 to  in the original graph.
    Little Q wonders the number of ways to delete edges to get such a satisfied graph. If there exists an edge between two nodes  and , while in another graph there isn't such edge, then we regard the two graphs different.
    Since the answer may be very large, please print the answer modulo .
     
    Input
    The input contains several test cases, no more than 10 test cases.
    In each test case, the first line contains an integer , denoting the number of nodes in the graph.
    In the following  lines, every line contains a string with  characters. These strings describes the adjacency matrix of the graph. Suppose the -th number of the -th line is , if  is a positive integer, there is an edge between  and  with length of , if , then there isn't any edge between  and .
    The input data ensure that the -th number of the -th line is always 0, and the -th number of the -th line is always equal to the -th number of the -th line.
     
    Output
    For each test case, print a single line containing a single integer, denoting the answer modulo .
     
    Sample Input
    
    
    2 01 10 4 0123 1012 2101 3210
     
    Sample Output
    
    
    1 6
     
    Source

    题意:给你一个图,让你删掉一些边后变成一棵树,这棵树的根是0号节点,要满足在树上从0到任意节点的最短距离和原图相等。问总共有多少种删法?

    做法:

    用dijkstra求出原图中0点到每个点的最短路的长度,再暴力的跑一遍判断能否通过别的点同样使得0点到当前点的距离仍是最短路径,如果有一个可替代点,则表示对于当前点存在一种可以删边的方法,将所有的可能删的方法相乘即可。

    #include <iostream>
    #include<cstring>
    #include<string>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<deque>
    #include<vector>
    #define ll long long
    #define inf 0x3f3f3f3f
    #define mod 1000000007;
    using namespace std;
    int n;
    int e[55][55];
    int d[55];
    bool book[55];
    void dij()
    {
        memset(d,inf,sizeof(d));
        memset(book,0,sizeof(book));
        for(int i=1;i<=n;i++) d[i]=e[1][i];
        book[1]=1;
        d[1]=0;
        int k=-1;
        int mi=inf;
        while(1)
        {
            k=-1;
            mi=inf;
            for(int i=1;i<=n;i++)
            {
                if(!book[i]&&d[i]<mi)
                {
                    mi=d[i];
                    k=i;
                }
            }
            if(k==-1) break;
            book[k]=1;
            for(int i=1;i<=n;i++)
            {
                if(!book[i]&&d[i]>d[k]+e[k][i])
                {
                    d[i]=d[k]+e[k][i];
                }
            }
        }
    }
    int main()
    {
        while(~scanf("%d",&n))
        {
            char s[55];
            for(int i=1;i<=n;i++)
            {
                cin>>s;
                for(int j=0;j<n;j++)
                {
                    if(s[j]=='0')
                    {
                        e[i][j+1]=inf;
                    }
                    else e[i][j+1]=s[j]-'0';
                }
            }
            dij();
            ll ans=1;
            ll temp=0;
            for(int i=2;i<=n;i++)
            {
                temp=0;
                for(int j=1;j<=n;j++)
                {
                    if(d[i]==d[j]+e[i][j])
                    {
                        temp++;
                    }
                }
                ans=(ans*temp)%mod;
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    c++中单引号和双引号的区别
    C++ 数组
    C++ 输出到文本文件
    C++中文本的读入
    C++ 输入和输出
    C++构造函数和文件组织
    Linux中使用gcc编译文件
    linux下修改gcc编译器版本
    Git--创建与合并分支
    'webpack' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
  • 原文地址:https://www.cnblogs.com/caiyishuai/p/13270992.html
Copyright © 2020-2023  润新知