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

咕咕咕

 

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;
}

 

posted @ 2019-07-31 20:02  darrrr  阅读(330)  评论(0编辑  收藏  举报