HDU - 6026 Deleting Edges / 2018年全国邀请赛(江苏)的K题

Deleting Edges

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


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  n nodes, labeled from 0 to  n1. 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  n1 edges.
(2) For every vertice  v(0<v<n), the distance between 0 and  v on the tree is equal to the length of shortest path from 0 to  v 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  i and  j, 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+7.
 

Input
The input contains several test cases, no more than 10 test cases.
In each test case, the first line contains an integer  n(1n50), denoting the number of nodes in the graph.
In the following  n lines, every line contains a string with  n characters. These strings describes the adjacency matrix of the graph. Suppose the  j-th number of the  i-th line is  c(0c9), if  c is a positive integer, there is an edge between  i and  j with length of  c, if  c=0, then there isn't any edge between  i and  j.
The input data ensure that the  i-th number of the  i-th line is always 0, and the  j-th number of the  i-th line is always equal to the  i-th number of the  j-th line.
 

Output
For each test case, print a single line containing a single integer, denoting the answer modulo  109+7.
 

Sample Input
 
 
2 01 10 4 0123 1012 2101 3210
 

Sample Output
 
 
1 6

    


做过两遍的原题比赛的时候愣是没写出来,真是日了狗了!!!

题意:给你一个含n个节点(n<=50,编号0~n-1)无向图,你要删去一些边,满足:

1、剩下的图是连通的。

2、剩下的图边数最少

3、原图中每个节点到源点0点的最短路上的边不能删。

求一共有多少种删法。

思路:  首先很容易想到,每一种删法对应原图的一颗生成树,因此我们只需要求有多少颗生成树即可。

于是先预处理出所有到源点0点的最短距离。

对于边(u,v),若dis[u]+len[u][v]==dis[v],则sum[v]++;   即从v点出发的可选边增加一条。

最后每个节点都选出一条出发的可选边即可组成一颗目标树,因此只需要乘起来累计答案即可。别忘了mod和long long

比赛的时候死活过不了,赛后补题1A,原因是赛场上写成了单向边。。。真tmd。。。

AC代码:

/*
我就是吃屎,也要A了这道题
*/
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn=110;
const ll mo=1e9+7;
int n,m;
struct node
{
    int to,de;
};
ll sum[maxn];
vector<node>g[maxn];
bool book[maxn];
int dis[maxn],d[maxn][maxn];
void init()
{
    memset(book,0,sizeof(book));
    memset(sum,0,sizeof(sum));
    for(int i=0;i<maxn;i++) g[i].clear();
    memset(dis,inf,sizeof(dis));
}
void spfa(int s)
{
    queue<int>q;
    q.push(s);
    book[s]=1;
    while(!q.empty())
    {
        int pt=q.front();
        q.pop();
        book[pt]=0;
        for(int i=0;i<g[pt].size();i++)
        {
            int tmp=g[pt][i].de+dis[pt];
            if(tmp<dis[g[pt][i].to])
            {
                dis[g[pt][i].to]=tmp;
                if(!book[g[pt][i].to])
                {
                    q.push(g[pt][i].to);
                    book[g[pt][i].to]=1;
                }
            }
        }
    }
}
char s[maxn][maxn];
int main()
{
    int i,x,y,j,c,T,cas;
    while(scanf("%d",&n)!=EOF)
    {
        init();
        m=n;
        for(int i=0;i<m;i++)
        {
            scanf("%s",s[i]);
        }
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        if(i!=j){
            int x=(s[i][j]&15);
            if(!x) continue;
            node k;
            k.de=x;
            k.to=j;
            g[i].push_back(k);
        }
        dis[0]=0;
        spfa(0);
        for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)//比赛的时候这里写成了i+1开始,无脑WA,真是日了狗了!!!
        if(j!=i){
            int x=(s[i][j]&15);
            if(!x) continue;
            if(dis[i]+x==dis[j]) sum[j]++;
        }
        ll ans=1;
        for(int i=1;i<n;i++) ans=(ans*sum[i])%mo;
        printf("%lld\n",ans);
    }
    return 0;
}

不要为了做题而做题,做过的题目一定要理解透彻!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值