zoukankan      html  css  js  c++  java
  • 【bzoj1922】 Sdoi2010—大陆争霸

    http://www.lydsy.com/JudgeOnline/problem.php?id=1922 (题目链接)

    题意

      一张无向图,每个节点被k个节点保护,想要走到一个节点当且仅当它不被保护。你可以从1号节点放出无限个炸弹去炸毁节点,问最少需要多久才可以炸毁n号节点。

    Solution

      昨天考试题。

      一看就是最短路然后带一些特殊处理,怎么特殊处理呢?我们使用Dijkstra来做这道题,因为SPFA可以重复入队,所以是错误的。每次出堆的点,将它保护的节点的“保护度数”减1并更新被保护节点的dis(取max),如果某个节点的度数已经被减成了0,并且它的dis不是inf,也就是说已经有一个炸弹在这个节点蓄势待发了,我们将这个节点加入堆中。做完减少度数操作后,就是正常的Dijkstra的入堆操作了,记得只有“保护度数”为0的点才能入堆。

    细节

      邻接表的数组开成了节点个数的大小→_→

    代码

    // bzoj1922
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cmath>
    #define LL long long
    #define inf 1e18
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=5010,maxm=100010;
    struct edge {int to,next,w;}e[maxm<<1];
    struct data {
    	int num;LL w;
    	friend bool operator < (const data a,const data b) {
    		return a.w>b.w;
    	}
    };
    LL dis[maxn];
    int head[maxn],vis[maxn],r[maxn];
    int cnt,n,m;
    vector<int> v[maxn];
    
    void link(int u,int v,int w) {
    	e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;e[cnt].w=w;
    }
    void Dijkstra() {
    	for (int i=1;i<=n;i++) dis[i]=inf;
    	dis[1]=0;
    	priority_queue<data> q;
    	q.push((data){1,0});
    	while (!q.empty() && !vis[n]) {
    		data x=q.top();q.pop();
    		if (vis[x.num]) continue;
    		vis[x.num]=1;
    		for (int i=0;i<v[x.num].size();i++) {
    			r[v[x.num][i]]--;
    			if (!r[v[x.num][i]] && dis[v[x.num][i]]!=inf)
    				q.push((data){v[x.num][i],max(dis[v[x.num][i]],x.w)});
    			dis[v[x.num][i]]=max(dis[v[x.num][i]],x.w);
    		}
    		for (int i=head[x.num];i;i=e[i].next) {
    			if (!vis[e[i].to] && dis[e[i].to]>x.w+e[i].w) {
    				dis[e[i].to]=x.w+e[i].w;
    				if (!r[e[i].to]) q.push((data){e[i].to,dis[e[i].to]});
    			}
    		}
    	}
    }
    int main() {
    	scanf("%d%d",&n,&m);
    	for (int uu,vv,ww,i=1;i<=m;i++) {
    		scanf("%d%d%d",&uu,&vv,&ww);
    		link(uu,vv,ww);
    	}
    	for (int i=1;i<=n;i++) {
    		scanf("%d",&r[i]);
    		for (int x,j=1;j<=r[i];j++) {
    			scanf("%d",&x);
    			v[x].push_back(i);
    		}
    	}
    	Dijkstra();
    	printf("%lld",dis[n]);
    	return 0;
    }
    

      

  • 相关阅读:
    Python经典算法-快速幂
    HTML/CSS代码片段
    JavaScript代码片段
    全选、全不选、反选
    NodeJS入门
    Ajax入门
    伪协议触发onbeforeunload
    CSS优先级、引入方式、Hack
    iframe的操作
    四:JAVA 消息队列(blockingqueue)的应用
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6030860.html
Copyright © 2011-2022 走看看