列表

详情


NC20337. [SDOI2010]大陆争霸

描述

在一个遥远的世界里有两个国家:位于大陆西端的杰森国和位于大陆东端的 克里斯国。两个国家的人民分别信仰两个对立的神:杰森国信仰象征黑暗和毁灭 的神曾·布拉泽,而克里斯国信仰象征光明和永恒的神斯普林·布拉泽。 
幻想历 8012年 1月,杰森国正式宣布曾·布拉泽是他们唯一信仰的神,同 时开始迫害在杰森国的信仰斯普林·布拉泽的克里斯国教徒。 
幻想历 8012年 3月2日,位于杰森国东部小镇神谕镇的克里斯国教徒发动 起义。 幻想历 8012年 3月7日,神谕镇的起义被杰森国大军以残酷手段镇压。 
幻想历 8012年 3月8日,克里斯国对杰森国宣战。由数十万大军组成的克 里斯军团开至两国边境,与杰森军团对峙。 
幻想历 8012年 4月,克里斯军团攻破杰森军团防线进入神谕镇,该镇幸存 的克里斯国教徒得到解放。 战争随后进入胶着状态,旷日持久。战况惨烈,一时间枪林弹雨,硝烟弥漫, 民不聊生。 
幻想历 8012年 5月12日深夜,斯普林·布拉泽降下神谕:“Trust me, earn eternal life.”克里斯军团士气大增。作为克里斯军团的主帅,你决定利用这一机会发动奇袭,一举击败杰森国。
具体地说,杰森国有 N 个城市,由 M条单向道路连接。神谕镇是城市 1而杰森国的首都是城市 N。你只需摧毁位于杰森国首都的曾·布拉泽大神殿,杰森国的信仰,军队还有一切就都会土崩瓦解,灰飞烟灭。 
为了尽量减小己方的消耗,你决定使用自爆机器人完成这一任务。唯一的困难是,杰森国的一部分城市有结界保护,不破坏掉结界就无法进入城市。而每个城市的结界都是由分布在其他城市中的一些结界发生器维持的,如果想进入某个 城市,你就必须破坏掉维持这个城市结界的所有结界发生器。 
现在你有无限多的自爆机器人,一旦进入了某个城市,自爆机器人可以瞬间引爆,破坏一个目标(结界发生器,或是杰森国大神殿),当然机器人本身也会一起被破坏。你需要知道:摧毁杰森国所需的最短时间。

输入描述

第一行两个正整数 N, M。 
接下来 M行,每行三个正整数 ui, vi, wi,表示有一条从城市ui到城市 vi的单向道路,自爆机器人通过这条道路需要 wi的时间。 
之后 N 行,每行描述一个城市。首先是一个正整数 li,维持这个城市结界所 使用的结界发生器数目。
之后li个1~N 之间的城市编号,表示每个结界发生器的位置。如果 Li = 0,则说明该城市没有结界保护,保证L1 = 0 。

输出描述

仅包含一个正整数 ,击败杰森国所需的最短时间。

示例1

输入:

6 6 
1 2 1 
1 4 3 
2 3 1 
2 5 2 
4 6 2 
5 3 2 
0 
0 
0 
1 3 
0 
2 3 5

输出:

5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 12ms, 内存消耗: 2256K, 提交时间: 2023-02-14 21:52:35

#include <cstdio>
#include <cmath>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#define ll long long
#define reg register
#define fo(a,b,c) for(reg int a=b;a<=c;a++)
#define re(a,b,c) for(reg int a=b;a>=c;a--)
#define pii pair<int,int>
#define fi first
#define se second
#define mod 1000000007
using namespace std;
inline ll gi(){
    ll x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
struct cop
{
	bool operator()(pii a,pii b)
	{
		return a.fi>b.fi;
	}
};
priority_queue<pii,vector<pii>,cop> q;
ll _=1;
struct io
{
	ll u,v,w;
}node[70005];
struct oi
{
	ll u,v;
}node1[5000005];
ll head[3005],dis[3005],head1[3005],cnt1,cnt,km[3005],ar[3005],in[3005],vis[3005];
void dij()
{
	while(!q.empty())
	{
		pii u=q.top();
		q.pop();
		if(vis[u.se]) continue;
		vis[u.se]=1;
		for(ll i=head1[u.se];i;i=node1[i].u)
		{
			ll v=node1[i].v;
			in[v]--;
			km[v]=max(km[v],ar[u.se]);
			if(in[v]==0)
			{
				if(ar[v]<99999999999999)
				{
					ar[v]=max(ar[v],km[v]);
					q.push({ar[v],v});
				}
			}
		}
		for(ll i=head[u.se];i;i=node[i].u)
		{
			ll v=node[i].v;
			if(in[v])
			{
				ar[v]=min(ar[v],ar[u.se]+node[i].w);
				continue;
			}
			if(ar[u.se]+node[i].w<ar[v])
			{
				ar[v]=ar[u.se]+node[i].w;
				q.push({ar[v],v});
			}
		}
	}
}
void add(ll u,ll v,ll w)
{
	cnt++;
	node[cnt].u=head[u];
	head[u]=cnt;
	node[cnt].v=v;
	node[cnt].w=w;
}
void add1(ll u,ll v)
{
	cnt1++;
	node1[cnt1].u=head1[u];
	head1[u]=cnt1;
	node1[cnt1].v=v;
}
void sol()
{
	memset(ar,0x3f,sizeof(ar));
	ll n=gi(),m=gi();
	ar[1]=0;
	fo(i,1,m)
	{
		ll x=gi(),y=gi(),z=gi();
		add(x,y,z);
	}
	fo(i,1,n)
	{
		ll k=gi();
		in[i]=k;
		fo(j,1,k)
		{
			ll x=gi();
			add1(x,i);
		}
	}
	q.push({0,1});
	dij();
	cout<<ar[n]<<'\n';
}
int main()
{
//	_=gi();
	while(_--)
	{
		sol();
//		cout<<'\n';
	}
	return 0;
}

C++(clang++ 11.0.1) 解法, 执行用时: 111ms, 内存消耗: 71636K, 提交时间: 2023-06-17 18:21:23

#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
typedef long long ll;
using namespace std;
const int N=3010;
const ll INF=0x3f3f3f3f3f3f3f3f;
int n,m,cnt[N];
ll dist[N][N],d[N];
vector<int> jj[N];
bool vis[N];
void dijkstra() {
    memset(d,0x3f,sizeof d);
    priority_queue<pair<ll,int>> pq;
    pq.push({0,1});
    d[1]=0;
    while(!pq.empty()) {
        int x=pq.top().second;ll y=pq.top().first;pq.pop();
        if(vis[x]) continue;
        vis[x]=true;
        for(int i=0;i<(int)jj[x].size();i++) {
            int t=jj[x][i];
            cnt[t]--;
            if(!cnt[t] && d[t]<INF) pq.push({-max(d[t],-y),t});
            d[t]=max(d[t],-y);
        }
        for(int i=1;i<=n;i++) {
            if(i==x || dist[x][i]>=INF) continue;
            if(d[i]>d[x]+dist[x][i]) {
                d[i]=d[x]+dist[x][i];
                if(!cnt[i]) pq.push({-d[i],i});
            }
        }
    }
}
int main() {
    scanf("%d%d",&n,&m);
    memset(dist,0x3f,sizeof dist);
    for(int i=1;i<=n;i++) dist[i][i]=0;
    while(m--) {
        int u,v;ll w;
        scanf("%d%d%lld",&u,&v,&w);
        dist[u][v]=min(dist[u][v],w);
    }
    for(int i=1;i<=n;i++) {
        cin>>cnt[i];
        for(int j=1;j<=cnt[i];j++) {
            int obs;
            cin>>obs;
            jj[obs].push_back(i);
        }
    }
    dijkstra();
    cout<<d[n];
    return 0;
}

上一题