省赛练习1——SDKD 2018 Spring Team Contest E&补题

      今下午组队打了一场省赛训练赛,感觉没发挥好,最终只A了4题,还有两题当时没能A,赛后补题的时候发现思路都对,只是代码处理有些小问题,当时跟队友怎么改都改不出来,一直是以为思路错了,没想到思路很对就是程序有点小瑕疵。。。

     首先是HDU - 6026 Deleting Edges(最短路径)

     

Little Q is crazy about graph theory, and now he creates a game about graphs and trees. 
There is a bi-directional graph with  nn nodes, labeled from 0 to  n1n−1. 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  n1n−1 edges. 
(2) For every vertice  v(0<v<n)v(0<v<n), the distance between 0 and  vv on the tree is equal to the length of shortest path from 0 to  vv 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  ii and  jj, 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  109+7109+7.
InputThe input contains several test cases, no more than 10 test cases. 
In each test case, the first line contains an integer  n(1n50)n(1≤n≤50), denoting the number of nodes in the graph. 
In the following  nn lines, every line contains a string with  nn characters. These strings describes the adjacency matrix of the graph. Suppose the  jj-th number of the  ii-th line is  c(0c9)c(0≤c≤9), if  cc is a positive integer, there is an edge between  ii and  jj with length of  cc, if  c=0c=0, then there isn't any edge between  ii and  jj
The input data ensure that the  ii-th number of the  ii-th line is always 0, and the  jj-th number of the  ii-th line is always equal to the  ii-th number of the  jj-th line.OutputFor each test case, print a single line containing a single integer, denoting the answer modulo  109+7109+7.Sample Input
2
01
10
4
0123
1012
2101
3210
Sample Output
1
6

      题意:给出一个图,要求删除一些边,然后使得删除后的图是一颗树,并且各个点到0点的距离为原来图中的最短距离:
     思路:先求出起点到各个点的最短距离,然后对各个点进行枚举,计算该点的临接点到他的距离为距离该点本身的最短距离数目,然后相乘;每个点的最短距离已确定,如果有多条路径到达这个点是他的最短距离的话,那么说明能够保留这些边的任何一条就行,所以有这些数目,然后进行相乘就是最终的结果;

      

#include <iostream>//应用前向星优化spfa算法
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int maxn=2502;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
struct node
{
    int to;
    int va;
    int next;
}edge[maxn];
int dis[maxn],vis[maxn],head[maxn],an[maxn];
queue<int>Q;
int ans=0;
int n;
void add(int u,int v,int w)
{
    edge[ans].to=v;//u指向的节点(孩子)
    edge[ans].va=w;
    edge[ans].next=head[u];//初始head[u]==-1,表示一个根节点,若head[u]!=-1,则存储的是节点u的兄弟节点的编号,
    head[u]=ans++;
}
void init()
{
    ans=0;
    memset(vis,0,sizeof(vis));
    memset(head,-1,sizeof(head));
    memset(an,0,sizeof(an));

}
void spfa()
{
    for(int i=1;i<=n;i++)dis[i]=INF;
    queue<int>Q;
    Q.push(0);
    dis[0]=0;
    vis[0]=1;
    while(!Q.empty())
    {
        int u=Q.front();Q.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            node e=edge[i];
            int v=e.to;
            //if(dis[v]==dis[u]+e.va)an[v]++;

            if(dis[v]>=dis[u]+e.va)
            {

                 dis[v]=dis[u]+e.va;
                //cout<<an[v]<<endl;
                if(!vis[v])
                {
                    vis[v]=1;
                    Q.push(v);
                }
            }
        }
    }
}
char a[maxn][maxn];
int main()
{
    while(~scanf("%d",&n))
    {
        init();
        for(int i=0;i<n;i++)
        {
            scanf("%s",a[i]);
            for(int j=0;j<n;j++)
            {
                if(i==j)continue;
                if((a[i][j]-'0'))add(i,j,a[i][j]-'0');
            }
        }
        spfa();
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(i!=j&&(a[i][j]-'0')&&dis[j]==dis[i]+a[i][j]-'0')an[j]++;
            }
        }
        long long sum=1;
        for(int i=1;i<n;i++)
        {
            //printf("%d\n",an[i]);
            sum=(sum*an[i])%mod;
        }
        printf("%lld\n",sum);
    }
    return 0;
}
           然后是HDU - 6029Graph Theory(找规律!!水题)

          

Little Q loves playing with different kinds of graphs very much. One day he thought about an interesting category of graphs called ``Cool Graph'', which are generated in the following way: 
Let the set of vertices be {1, 2, 3, ...,  nn}. You have to consider every vertice from left to right (i.e. from vertice 2 to  nn). At vertice  ii, you must make one of the following two decisions: 
(1) Add edges between this vertex and all the previous vertices (i.e. from vertex 1 to  i1i−1). 
(2) Not add any edge between this vertex and any of the previous vertices. 
In the mathematical discipline of graph theory, a matching in a graph is a set of edges without common vertices. A perfect matching is a matching that each vertice is covered by an edge in the set. 
Now Little Q is interested in checking whether a ''Cool Graph'' has perfect matching. Please write a program to help him. 
InputThe first line of the input contains an integer  T(1T50)T(1≤T≤50), denoting the number of test cases. 
In each test case, there is an integer  n(2n100000)n(2≤n≤100000) in the first line, denoting the number of vertices of the graph. 
The following line contains  n1n−1 integers  a2,a3,...,an(1ai2)a2,a3,...,an(1≤ai≤2), denoting the decision on each vertice.OutputFor each test case, output a string in the first line. If the graph has perfect matching, output ''Yes'', otherwise output ''No''. 
Sample Input
3
2
1
2
2
4
1 1 2
Sample Output
Yes
No
No

          题意:有n个点,1表示当前点与之前所有点连一条边,2表示不操作,问通过选出其中的某些边,能否使所有的点都能够有一个点与其“完美配对”。
          思路:
用cnt表示前面有多少个未配对的点,如果前面有未配对的点则,若操作为1,,则cnt--,若操作为2则cnt++

如果前面所有的点都匹对成功则,若操作为1,,则cnt=1(因为前面没有点与其配对),若操作为2则cnt++

#include<iostream>  
#include<algorithm>  
#include<cmath>  
#include<cstdio>  
const int maxn = 100010;  
int n, a[maxn];  
int main()  
{  
    int t;  
    scanf("%d", &t);  
    while (t--)  
    {  
        int cnt = 1;  
        scanf("%d", &n);  
        for (int i = 2; i <= n; i++)  
        {  
            scanf("%d", a + i);  
        }  
        if (n % 2 != 0) puts("No");  
        else  
        {  
            for (int i = 2; i <= n; i++)  
            {  
                if (a[i] == 1)  
                {  
                    if (cnt == 0) cnt = 1;  
                    else cnt--;  
                }  
                else cnt++;  
            }  
            if (cnt > 0) puts("No");  
            else puts("Yes");  
        }  
    }  
} 

猜你喜欢

转载自blog.csdn.net/qq_35739903/article/details/80100064