省賽練習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");  
        }  
    }  
} 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章