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

  

原文地址:https://www.cnblogs.com/MashiroSky/p/6030860.html