黑暗城堡-(最小生成树+最短路)

Posted darlingroot

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了黑暗城堡-(最小生成树+最短路)相关的知识,希望对你有一定的参考价值。

咕咕咕

 

prim的特点是从一个点开始,不断把距离最短的点加入图中,在以此延伸。是一种贪心的想法。当知道prim的特点的时候,就可以想到这题用prim。

这题又要求实际路径=最短路径,,也可以想到用dijkstra。

具体做法:

用dijkstra求出1号犯贱到每个房间的单元最短路。把树形城堡看做以1为根的有根树。

把所有节点按照dis值排序,从小到大一次考虑吧每个节点p加入树形城堡有多少种方法。

和prim类似,维护“最短路径生成树”的一部分记为T

统计有多少个节点x满足,x∈T并且dis[ p ] = dis [ x ] + edge ( x , p ),其中edge表示边的长度。

让p与其中任意一个x项链都符合题目的要求。

根据乘法原理,把每一步统计出的数据乘起来,即可得答案。

#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
#define mk make_pair
#define ll long long
using namespace std;
inline int read()

    int sum = 0,p = 1;
    char ch = getchar();
    while(ch < 0 || ch > 9)
    
        if(ch == -)
            p = -1;
        ch = getchar();
    
    while(ch >= 0 && ch <= 9)
    
        (sum *= 10) += ch - 0;
        ch = getchar();
     
    return sum * p;


const int M = 5e5 + 10;
const int N = 1e3 + 5;
const int mod = 2147483647;
int n,m;
int head[N],cnt;
struct edge

    int nxt,to,wei;
e[M<<1];
priority_queue<pair<int,int> > q;
bool vis[N];
int dis[N],sum[N];
struct pot

    int id,dis;
p[N];

void add(int x,int y,int v)//加边 

    e[++cnt].nxt = head[x];
    e[cnt].to = y;
    e[cnt].wei = v;
    head[x] = cnt;


void dijkstra()

    memset(dis,0x3f,sizeof(dis));
    dis[1] = 0;
    q.push(mk(0,1));
    while(q.size())
    
        int u = q.top().second;
        q.pop();
        if(vis[u])
            continue;
        vis[u] =true;
        for(int i = head[u];i;i = e[i].nxt)
        
            int v = e[i].to;
            if(dis[u] + e[i].wei < dis[v])
            
                dis[v] = dis[u] +e[i].wei;
                q.push(mk(-dis[v],v));
            
         
    


bool cmp(pot a,pot b)

    return a.dis < b.dis;


int main()

    n = read(),m = read();
    for(int i = 1;i <= m;i++)
    
        int x = read(),y = read(),l = read();
        add(x,y,l);
        add(y,x,l); 
     
    dijkstra();
    
//    for(int i = 1;i <= n;i++)
//        printf("%d-===-%d\n",i,dis[i]);
//    puts("\n");
    
    for(int i = 1;i <= n;i++)
    
        p[i].id = i;
        p[i].dis = dis[i];
    
    sort(p+1,p+n+1,cmp);
    memset(vis,false,sizeof(vis));
    vis[1] = true;
    for(int i = 2;i <= n;i++)
    
        vis[p[i].id] = true;
        for(int j = head[p[i].id];j;j = e[j].nxt)
        
            int v = e[j].to;
            if(vis[v] && dis[v] + e[j].wei == p[i].dis)
                sum[i]++;
        
    
//    for(int i = 1;i <= n;i++)
//        printf("%d----%d\n",i,sum[i]);
        
    ll ans = 1;
    for(int i = 2;i <= n;i++)
        ans = (ans * sum[i])%mod;
    printf("%lld",ans);
    return 0;

 

以上是关于黑暗城堡-(最小生成树+最短路)的主要内容,如果未能解决你的问题,请参考以下文章

CH6202 黑暗城堡

黑暗城堡

经典树与图论(最小生成树、哈夫曼树、最短路径问题---Dijkstra算法)

《算法进阶指南》最小生成树剩余题目

黑暗城堡

习题—最小生成树单源最短路所有节点对最短路