(2019南昌网络赛) B. Fire-Fighting Hero E. Magic Master

传送门

 

B. Fire-Fighting Hero

解:给消防队加一个源点0,从他开始跑一次dijkstra,再取最大值。消防英雄的话跑一次,两次dijkstra即可。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define SZ(a) int((a).size())
using namespace std;
typedef long long ll;
const ll inf=1e18+5;
const int maxn=1e3+5;
struct node {
	ll p,dis;
	bool operator <(const node& x)const {
		return dis>x.dis;
	}
};
struct edge {
	ll to,w;
};
vector<edge> e[maxn];
bool vis[maxn];
ll dist[maxn];
int n,m,s,k,c;
il void Dijkstra(int start) {
	for(int i=0; i<=n; ++i) dist[i]=inf,vis[i]=false;
	dist[start]=0;
	priority_queue<node> q;
	q.push(node {start,0});
	while(!q.empty()) {
		node tmp=q.top();
		q.pop();
		int np=tmp.p;
		if(vis[np])	continue;
		else {
			vis[np]=1;
			for(int i=0; i<e[np].size(); ++i) {
				edge ne=e[np][i];
				ll nto=ne.to,nw=ne.w;
				if(dist[nto]>dist[np]+nw) {
					dist[nto]=dist[np]+nw;
					q.push(node {nto,dist[nto]});
				}
			}
		}
	}
}
//il int Add(ll &x,ll y) {return x=x+y>=mod?x+y-mod:x+y;}
//il int Mul(ll &x,ll y) {return x=x*y>=mod?x*y%mod:x*y;}
int T,p[maxn];
int main() {
	scanf("%d",&T);
	unordered_set<int> fr;
	while(T--) {
		fr.clear();
		scanf("%d%d%d%d%d",&n,&m,&s,&k,&c);
		for(int i=0; i<=n; ++i) e[i].clear();
		for(int i=0; i<k; i++) {
			scanf("%d",p+i);
			e[0].push_back({p[i],0});
		}
		int u,v,l;
		for(int i=0; i<m; i++) {
			scanf("%d%d%d",&u,&v,&l);
			fr.insert(v),fr.insert(u);
			e[u].push_back({v,l});
			e[v].push_back({u,l});
		}
		ll H=0,P=0;
		Dijkstra(s);
		for(auto it = fr.begin(); it!=fr.end(); ++it) {
			H=max(dist[*it],H);
		}
		Dijkstra(0);
		for(auto it = fr.begin(); it!=fr.end(); ++it) {
			P=max(dist[*it],P);
		}
		if(H>1LL*P*c) printf("%lld\n",P);
		else printf("%lld\n",H);
	}
	return 0;
}








一开始那个解法假了,数据太弱了。

E. Magic Master

解:就是约瑟夫环,根据题意,那就是第几个拿出来的那就是第几,直接用静态链表模拟即可(4e9)。

开数组比开结构体快了将近一倍,被卡成憨憨。

#include<bits/stdc++.h>
#define il inline
#define pb push_back
#define ms(_data,v) memset(_data,v,sizeof(_data))
#define SZ(a) int((a).size())
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f;
const int N=4e7+5;
//il int Add(ll &x,ll y) {return x=x+y>=mod?x+y-mod:x+y;}
//il int Mul(ll &x,ll y) {return x=x*y>=mod?x*y%mod:x*y;}
int T,ans[N];
int pre[N],nxt[N];
int main() {
	scanf("%d",&T);
	int n,m,q,x;
	while(T--) {
		scanf("%d%d%d",&n,&m,&q);
		for(int i=1; i<=n; ++i) {
			if(i==1) pre[i]=n;
			else pre[i]=i-1;
			if(i==n) nxt[i]=1;
			else nxt[i]=i+1;
		}
		if(n==2) {
			ans[1]=1,ans[2]=2;
		} else {
			ans[1]=1;
			pre[2]=pre[1];
			nxt[pre[1]]=nxt[1];
			n--;
			int nt,j=2,cnt=1;
			int npre,nnxt;
			while(n) {
				nt=m;
				while(nt--) {
					j=nxt[j];
				}
				ans[j]=++cnt;
				if(n==2) {
					ans[nxt[j]]=++cnt;
					break;
				}
				npre=pre[j],nnxt=nxt[j];
				j=nxt[j];
				nxt[npre]=nnxt,pre[nnxt]=npre;
				n--;
			}
		}
		while(q--) {
			scanf("%d",&x);
			printf("%d\n",ans[x]);
		}
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值