城堡 (spfa+cheng)

【问题描述】

给定一张?个点?条边的无向连通图,每条边有边权。我们需要从?条边中
选出? − 1条, 构成一棵树。 记原图中从 1 号点到每个节点的最短路径长度为? ? ,
树中从 1 号点到每个节点的最短路径长度为? ? ,构出的树应当满足对于任意节点
?,都有? ? = ? ? 。

请你求出选出? − 1条边的方案数。

【输入格式】

输入的第一行包含两个整数?和?。
接下来?行,每行包含三个整数?、?和?,描述一条连接节点?和?且边权为
?的边。

【输出格式】

输出一行,包含一个整数,代表方案数对2 31 − 1取模得到的结果。

【样例输入】

3 3
1 2 2
1 3 1
2 3 1

【样例输出】

2

【数据规模和约定】

32 ≤ ? ≤ 5,? ≤ 10。
对于50%的数据,满足条件的方案数不超过 10000。
对于100%的数据,2≤ ? ≤ 1000,? − 1 ≤ ? ≤
? ?−1
2
,1 ≤ ? ≤ 100。

思路:

  按照题目里的说的模拟

  先跑一遍spfa得出单源最短路

  然后对于每一个点枚举所有与它相连的点

  如果与它相连的点的dis值加上这条边的权值等于它的dis值

  则这个点的价值加一

  所有的点枚举完后

  把价值为0的点赋值为1

  然后所有点的价值相乘

  即可得出答案

  但是

  你以为这就是正解?

  别忘了取mod(因为这个我没了40分)

  有mod才是正解

来,上代码:

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

struct node {
    int from,to,dis,next;
};
struct node edge[1000005];

const long long int mod=2147483647;

int num_head,num_edge,num_1=0,head[1001];
int dis_1[1001],tree_leaf[1001],num_leaf=1;

long long int ans_edge=1;
long long int num_edge_tree[1001];

char word;

bool if_in_tree[1001];

queue<int>q;

inline void edge_add(int from,int to,int dis)
{
    num_1++;
    edge[num_1].to=to;
    edge[num_1].dis=dis;
    edge[num_1].from=from;
    edge[num_1].next=head[from];
    head[from]=num_1;
}

inline void read_int(int &now_001)
{
    now_001=0;word=getchar();
    while(word>‘9‘||word<‘0‘) word=getchar();
    while(word>=‘0‘&&word<=‘9‘)
    {
        now_001=now_001*10+(int)(word-‘0‘);
        word=getchar();
    }
}

void map_spfa()
{
    bool if_in_spfa[1001];
    memset(dis_1,127/3,sizeof(dis_1));
    memset(if_in_spfa,false,sizeof(if_in_spfa));
    dis_1[1]=0;
    if_in_spfa[1]=true;
    q.push(1);
    int cur_1,cur_2;
    while(!q.empty())
    {
        cur_1=q.front();
        for(int i=head[cur_1];i!=0;i=edge[i].next)
        {
            if(dis_1[cur_1]+edge[i].dis<dis_1[edge[i].to])
            {
                dis_1[edge[i].to]=dis_1[cur_1]+edge[i].dis;
                if(!if_in_spfa[edge[i].to])
                {
                    q.push(edge[i].to);
                    if_in_spfa[edge[i].to]=true;
                }
            }
        }
        if_in_spfa[cur_1]=false;
        q.pop();
    }
}

int main()
{
    read_int(num_head),read_int(num_edge);
    int from,to,dis;
    for(int i=1 ; i<=num_edge ; i++)
    {
        read_int(from),read_int(to),read_int(dis);
        edge_add(from,to,dis);
        edge_add(to,from,dis);
    }
    map_spfa();
    for(int j=1;j<=num_head;j++)
    {
        for(int i=head[j];i!=0;i=edge[i].next)
        {
            if(edge[i].dis+dis_1[j]==dis_1[edge[i].to])
            {
                num_edge_tree[edge[i].to]++;
                num_edge_tree[edge[i].to]%=mod;
            }
        }
    }
    for(int i=1;i<=num_head;i++) if(num_edge_tree[i]==0) num_edge_tree[i]=1;
    for(int i=1;i<=num_head;i++)
    {
        ans_edge*=num_edge_tree[i];
        ans_edge%=mod;
    }
    cout<<ans_edge<<endl;
    return 0;
}
时间: 2024-10-05 19:28:13

城堡 (spfa+cheng)的相关文章

ACM/ICPC 之 最短路-Floyd+SPFA(BFS)+DP(ZOJ1232)

这是一道非常好的题目,融合了很多知识点. ZOJ1232-Adventrue of Super Mario 这一题折磨我挺长时间的,不过最后做出来非常开心啊,哇咔咔咔 题意就不累述了,注释有写,难点在于状态转移方程的确立和SPFA的过程 1 //最短路:Floyd+SPFA(BFS)+DP 2 //Time:20Ms Memory:336K 3 //题目很好,数据较弱,网上部分代码有些问题却能够A掉 4 //题意:超级马里奥要从A+B处背着公主以最短路程到达1处,其中1-A是村庄,剩下的是城堡

UESTC30-最短路-Floyd最短路、spfa+链式前向星建图

最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的T-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据. 每组数据第一行是两个整数NN ,MM (N≤100N≤100 ,M≤10000M≤1000

畅通project续HDU杭电1874【dijkstra算法 || SPFA】

http://acm.hdu.edu.cn/showproblem.php?pid=1874 Problem Description 某省自从实行了非常多年的畅通project计划后.最终修建了非常多路.只是路多了也不好,每次要从一个城镇到还有一个城镇时,都有很多种道路方案能够选择,而某些方案要比还有一些方案行走的距离要短非常多.这让行人非常困扰. 如今,已知起点和终点,请你计算出要从起点到终点.最短须要行走多少距离. Input 本题目包括多组数据.请处理到文件结束. 每组数据第一行包括两个正

HDU 2722 Here We Go(relians) Again (spfa)

Here We Go(relians) Again Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 1   Accepted Submission(s) : 1 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description The Gorelians

[BZOJ 1295][SCOI2009]最长距离(SPFA+暴力)

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1295 分析:很巧妙的一道spfa从搜索的角度是搜索在所有1中搜索删除哪T个1,对整个图询问,这样肯定TLE 不妨反过来想一想:对于两个点,弄出联通这两个点所需删除的最少的1,那么就知道这两个点是否可以作为题目要求的起点和终点,如果满足算一下结果和ans比较一下就可以. 所以算法就出来了: 枚举起点(S,T),用SPFA跑出图上的所有点到起点这条路径联通的最少删除的1,那么ans=max(di

poj3268 Silver Cow Party (SPFA求最短路)

其实还是从一个x点出发到所有点的最短路问题.来和回只需分别处理一下逆图和原图,两次SPFA就行了. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<map> #include<set> #include<vector> #

POJ--3259--Wormholes【SPFA判负权值回路】

题意:有n个点,之间有m条双向路径,还有w个虫洞,单向,从一点到另一点需要花费时间,但是有虫洞的话会减少时间,一个人想要走某一条路使得他能碰到过去的自己,问这个图是否能让他实现他的想法. 其实就是判一个图是否存在负权值回路,SPFA可以实现,原理是:如果存在负权值回路,那么从源点到某个顶点的距离就可以无限缩短,因此就会无限入队,所以在SPFA中统计每个顶点的入队次数,如果超过了n个(顶点个数)则说明存在负权值回路. 我把输出yes和输出no写反了,WA了两发,看了半天都没发现... #inclu

POJ 3259 Wormholes SPFA算法题解

本题其实也可以使用SPFA算法来求解的,不过就一个关键点,就是当某个顶点入列的次数超过所有顶点的总数的时候,就可以判断是有负环出现了. SPFA原来也是可以处理负环的. 不过SPFA这种处理负环的方法自然比一般的Bellman Ford算法要慢点了. #include <stdio.h> #include <string.h> #include <limits.h> const int MAX_N = 501; const int MAX_M = 2501; const

ZOJ 3794 Greedy Driver spfa

题意: 给定n个点,m条有向边,邮箱容量. 起点在1,终点在n,开始邮箱满油. 下面m行表示起点终点和这条边的耗油量(就是长度) 再下面给出一个数字m表示有P个加油站,可以免费加满油. 下面一行P个数字表示加油站的点标. 再下面一个整数Q 下面Q行 u v 表示在u点有销售站,可以卖掉邮箱里的任意数量的油,每以单位v元. 问跑到终点能获得最多多少元. 先求个每个点的最大剩余油量 f[i], 再把边反向,求每个点距离终点的最短路 dis[i]. 然后枚举一下每个销售点即可,( f[i] - dis