bzoj1922大陆争霸

题意

无向图,从一个点到另一个点需要一定的时间,可以从1号节点出发放出无限个炸弹去摧毁某些点,每个节点被k个节点保护,一个点只有当保护它的点被摧毁后才能到达,求到达点n最短用时。

分析

最短路,用Dijkstra而非Spfa。
Dijkstra与Spfa的区别:Dijkstra从队列中取出的点一定是最短路已经确定的点而Spfa不一定。
对于每一个点,记录保护它的点的数量,只有当保护它的点都被摧毁且dis!=INF时将其放入队列。

#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
#define MAXN 3010
#define MAXM 70010
#define INF 100000000
int Adj[MAXN],nxt[MAXM],V[MAXM],w[MAXM],c;
void AddEdge(int u,int v,int t)
{
    c++;
    V[c]=v,w[c]=t;
    nxt[c]=Adj[u];Adj[u]=c;
}
typedef pair<int,int> PII;
vector<int>G[MAXN];
int du[MAXN],dis[MAXN];
void Dijkstra()
{
    priority_queue<PII,vector<PII>,greater<PII> > Q;
    Q.push(PII(0,1));
    dis[1]=0;
    while(!Q.empty())
    {
        PII p=Q.top();Q.pop();
        int u=p.second;
        if(dis[u]!=p.first) continue;
        int v;
        for(int i=0;i<G[u].size();i++)
        {
            v=G[u][i];
            du[v]--;
            dis[v]=max(dis[v],dis[u]);
            if(du[v]==0&&dis[v]!=INF)
                Q.push(PII(dis[v],v));
        }
        for(int i=Adj[u];i;i=nxt[i])
        {
            v=V[i];
            if(dis[v]>dis[u]+w[i])
            {
                dis[v]=dis[u]+w[i];
                if(du[v]==0)
                    Q.push(PII(dis[v],v));
            }
        }
    }
}
int main()
{
    int n,m,u,v,x;
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&u,&v,&x);
        AddEdge(u,v,x);
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        du[i]=x;
        while(x--)
        {
            scanf("%d",&u);
            G[u].push_back(i);
        }
    }
    for(int i=1;i<=n;i++)
        dis[i]=INF;
    Dijkstra();
    printf("%d\n",dis[n]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41343943/article/details/82289515
今日推荐