zoukankan      html  css  js  c++  java
  • [SDOI2010]大陆争霸

    带限制的最短路

    这道题是我做的第一个带限制的最短路题,所以许多细节我思考了好长时间并看了题解才会的。

    首先我们关注条件:机器人无限个,所以我们可以认为有无限个机器人从1号点同时出发。摧毁一个点的代价为max(到达他的代价,破坏他的所有的保护器的代价);所以我们可以开三个数组和一个vector。三个数组分别表示到达该点的代价d1,破坏他的所有的保护器的代价d2,还有他有多少个保护器inde。vector用来存该点保护了哪些点,我一开始想反了。为什么要这样?我们更新摧毁该点的代价时可以更新他保护的城市的d2。最后一遍dij就好了(见代码注释)

    code:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<queue>
    #include<cstring>
    #include<vector>
    #include<stack>
    #define SUPER_INT signed
    using namespace std;
    const int maxn=400006;
    struct hzw
    {
        int to,next,v;
    }e[maxn];
    vector<int>v[maxn];
    typedef pair<int,int>p;
    int head[maxn],cur,inde[maxn],da[maxn],db[maxn],n,m,k;
    inline void add(int a,int b,int c)
    {
        e[cur].to=b;
        e[cur].next=head[a];
        e[cur].v=c;
        head[a]=cur++;
    }
    bool vis[maxn];
    inline void dij(int shit)
    {
        priority_queue<p,vector<p>,greater<p> >q;
        memset(da,0x3f,sizeof(da));
        da[shit]=0;
        q.push(p(0,shit));
        while (!q.empty())
        {
            p now=q.top();
            q.pop();
            int s=now.second;
            if (vis[s]) continue;
            vis[s]=1;			
    		int tmp=max(da[s],db[s]);//破坏这个点实际的代价 
            for (int i=head[s];i!=-1;i=e[i].next)
            {
            	int vv=e[i].to;
            	if (da[vv]>tmp+e[i].v)
            	{
            		da[vv]=tmp+e[i].v;//更新连接的点:到达它需要的代价 
            		if (inde[vv]==0) q.push(p(da[vv],vv)); //如果本来就没有保护器,直接入队 
    			}
            }
            for (int i=0;i<v[s].size();++i)
            {
            	int vv=v[s][i];
            	inde[vv]--; 
            	db[vv]=max(db[vv],tmp);//更新该点保护的城市的db值(取max,因为机器人同时出发) 
    			if (!inde[vv]) q.push(p(max(db[vv],da[vv]),vv));//如果所保护的城市已经没有保护器了,就入队 
    		}
        }
        cout<<max(da[n],db[n]);//good game !  
    }
    SUPER_INT main()
    {
        memset(head,-1,sizeof(head));
    	cin>>n>>m;
        for (int i=1,a,b,c;i<=m;++i)
        {
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c);
        }
        for (int i=1,a;i<=n;++i)
        {
            scanf("%d",&a);
            for (int j=1,b;j<=a;++j)
            {
            	inde[i]++;
                scanf("%d",&b);
                v[b].push_back(i);
            }
        }
        dij(1);
    }
    

    收获:

    带限制的最短路问题往往有几个条件,就要开几个数组,在跑最短路的过程中不断更新各个参数,注意这类形如xx受到yy,的问题:一般要存yy保护了哪些点,方便更新

  • 相关阅读:
    2012 Multi-University #8
    2016"百度之星"
    Codeforces Round #352 (Div. 2)
    数位DP CF 55D Beautiful numbers
    数位DP GYM 100827 E Hill Number
    2012 Multi-University #9
    2012 Multi-University #10
    java生成指定范围的随机数
    MySql查询时间段的方法
    eclipse报错GC overhead limit exceed,卡顿
  • 原文地址:https://www.cnblogs.com/bullshit/p/9699546.html
Copyright © 2011-2022 走看看